home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / gepackte_disketten / 1994 / 08_94_5.dms / 08_94_5.adf / term-4.0-Source.lha / termAux.c < prev    next >
C/C++ Source or Header  |  1994-07-15  |  72KB  |  3,896 lines

  1. /*
  2. **    termAux.c
  3. **
  4. **    Miscellaneous support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* This variable stores the current state of the
  13.      * dialing menu items.
  14.      */
  15.  
  16. STATIC BYTE DialItemsAvailable = TRUE;
  17.  
  18.     /* Current timer state. */
  19.  
  20. STATIC BYTE TimerRunning = FALSE;
  21.  
  22.     /* StripSpaces(STRPTR String):
  23.      *
  24.      *    Strip leading and trailing spaces from a string.
  25.      */
  26.  
  27. VOID __regargs
  28. StripSpaces(STRPTR String)
  29. {
  30.     if(String)
  31.     {
  32.         STRPTR    To = String;
  33.         WORD    Len;
  34.  
  35.         while(*String == ' ')
  36.             String++;
  37.  
  38.         if(Len = strlen(String))
  39.         {
  40.             while(Len > 0 && String[Len - 1] == ' ')
  41.                 Len--;
  42.  
  43.             while(Len--)
  44.                 *To++ = *String++;
  45.         }
  46.  
  47.         *To = 0;
  48.     }
  49. }
  50.  
  51.     /* ReplaceWindowInfo(struct WindowInfo *NewInfo):
  52.      *
  53.      *    Drop the window info into the right place.
  54.      */
  55.  
  56. VOID __regargs
  57. ReplaceWindowInfo(struct WindowInfo *NewInfo)
  58. {
  59.     WORD i;
  60.  
  61.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  62.     {
  63.         if(WindowInfoTable[i] . ID == NewInfo -> ID)
  64.         {
  65.             CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
  66.  
  67.             break;
  68.         }
  69.     }
  70. }
  71.  
  72.     /* PutWindowInfo():
  73.      *
  74.      *    Store window size and position relative to
  75.      *    the main window.
  76.      */
  77.  
  78. VOID __regargs
  79. PutWindowInfo(UBYTE ID,LONG Left,LONG Top,LONG Width,LONG Height)
  80. {
  81.     struct WindowInfo    *Info;
  82.     WORD             i;
  83.     LONG             WindowLeft,
  84.                  WindowTop,
  85.                  WindowWidth,
  86.                  WindowHeight;
  87.     ULONG             IntuiLock;
  88.  
  89.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  90.     {
  91.         if(WindowInfoTable[i] . ID == ID)
  92.         {
  93.             Info = &WindowInfoTable[i];
  94.  
  95.             break;
  96.         }
  97.     }
  98.  
  99.     IntuiLock = LockIBase(NULL);
  100.  
  101.     WindowLeft    = Window -> LeftEdge;
  102.     WindowTop    = Window -> TopEdge;
  103.     WindowWidth    = Window -> Width;
  104.     WindowHeight    = Window -> Height;
  105.  
  106.     UnlockIBase(IntuiLock);
  107.  
  108.     Forbid();
  109.  
  110.     Info -> WindowFlags = NULL;
  111.  
  112.     if(WindowWidth == Width && WindowLeft == Left)
  113.         Info -> WindowFlags |= WC_EXPANDWIDTH;
  114.     else
  115.     {
  116.         if(Left == WindowLeft + WindowWidth)
  117.             Info -> WindowFlags |= WC_ALIGNSIDE;
  118.  
  119.         if(WindowLeft == Left)
  120.             Info -> WindowFlags |= WC_ALIGNLEFT;
  121.  
  122.         if(WindowLeft + WindowWidth == Left + Width)
  123.             Info -> WindowFlags |= WC_ALIGNRIGHT;
  124.     }
  125.  
  126.     if(WindowHeight == Height && WindowTop == Top)
  127.         Info -> WindowFlags |= WC_EXPANDHEIGHT;
  128.     else
  129.     {
  130.         if(Top == WindowTop + WindowHeight)
  131.             Info -> WindowFlags |= WC_ALIGNBELOW;
  132.  
  133.         if(WindowTop == Top)
  134.             Info -> WindowFlags |= WC_ALIGNTOP;
  135.  
  136.         if(WindowTop + WindowHeight == Top + Height)
  137.             Info -> WindowFlags |= WC_ALIGNBOTTOM;
  138.     }
  139.  
  140.     Info -> Left    = Left;
  141.     Info -> Top    = Top;
  142.     Info -> Width    = Width;
  143.     Info -> Height    = Height;
  144.  
  145.     Permit();
  146. }
  147.  
  148.     /* GetWindowInfo():
  149.      *
  150.      *    Set the window size and position in relation to
  151.      *    the main window.
  152.      */
  153.  
  154. VOID __regargs
  155. GetWindowInfo(UBYTE ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
  156. {
  157.     struct WindowInfo    *Info;
  158.     WORD             i;
  159.     LONG             WindowLeft,
  160.                  WindowTop,
  161.                  WindowWidth,
  162.                  WindowHeight;
  163.     ULONG             IntuiLock;
  164.  
  165.     if(DefWidth && DefWidth < Window -> Width / 2)
  166.         DefWidth = Window -> Width / 2;
  167.  
  168.     if(DefHeight && DefHeight < Window -> Height / 2)
  169.         DefHeight = Window -> Height / 2;
  170.  
  171.     for(i = 0 ; i < WINDOW_COUNT ; i++)
  172.     {
  173.         if(WindowInfoTable[i] . ID == ID)
  174.         {
  175.             Info = &WindowInfoTable[i];
  176.  
  177.             break;
  178.         }
  179.     }
  180.  
  181.     IntuiLock = LockIBase(NULL);
  182.  
  183.     WindowLeft    = Window -> LeftEdge;
  184.     WindowTop    = Window -> TopEdge;
  185.     WindowWidth    = Window -> Width;
  186.     WindowHeight    = Window -> Height;
  187.  
  188.     UnlockIBase(IntuiLock);
  189.  
  190.     Forbid();
  191.  
  192.     if(*Width)
  193.     {
  194.         if(Info -> Width)
  195.             *Left = Info -> Left;
  196.         else
  197.             *Left = WindowLeft + (WindowWidth - *Width) / 2;
  198.     }
  199.     else
  200.     {
  201.         if(DefWidth && !Info -> Width)
  202.         {
  203.             *Width    = DefWidth;
  204.             *Left    = WindowLeft + (WindowWidth - *Width) / 2;
  205.         }
  206.         else
  207.         {
  208.             if(Info -> Width)
  209.             {
  210.                 *Width    = Info -> Width;
  211.                 *Left    = Info -> Left;
  212.             }
  213.             else
  214.             {
  215. /*                *Width    = WindowWidth / 2;*/
  216. /*                *Left    = WindowLeft + WindowWidth / 4;*/
  217.  
  218.                 *Width    = WindowWidth;
  219.                 *Left    = WindowLeft;
  220.             }
  221.         }
  222.     }
  223.  
  224.     if(*Height)
  225.     {
  226.         if(Info -> Height)
  227.             *Top = Info -> Top;
  228.         else
  229.             *Top = WindowTop + (WindowHeight - *Height) / 2;
  230.     }
  231.     else
  232.     {
  233.         if(DefHeight && !Info -> Height)
  234.         {
  235.             *Height    = DefHeight;
  236.             *Top    = WindowTop + (WindowHeight - *Height) / 2;
  237.         }
  238.         else
  239.         {
  240.             if(Info -> Height)
  241.             {
  242.                 *Height    = Info -> Height;
  243.                 *Top    = Info -> Top;
  244.             }
  245.             else
  246.             {
  247. /*                *Height    = WindowHeight / 2;*/
  248. /*                *Top    = WindowTop + WindowHeight / 4;*/
  249.  
  250.                 *Height    = WindowHeight;
  251.                 *Top    = WindowTop;
  252.             }
  253.         }
  254.     }
  255.  
  256.     if(Info -> WindowFlags & WC_ALIGNSIDE)
  257.         *Left = WindowLeft + WindowWidth;
  258.  
  259.     if(Info -> WindowFlags & WC_ALIGNBELOW)
  260.         *Top = WindowTop + WindowHeight;
  261.  
  262.     if(Info -> WindowFlags & WC_ALIGNLEFT)
  263.         *Left = WindowLeft;
  264.  
  265.     if(Info -> WindowFlags & WC_ALIGNTOP)
  266.         *Top = WindowTop;
  267.  
  268.     if(Info -> WindowFlags & WC_ALIGNRIGHT)
  269.         *Left = WindowLeft + WindowWidth - *Width;
  270.  
  271.     if(Info -> WindowFlags & WC_ALIGNBOTTOM)
  272.         *Top = WindowTop + WindowHeight - *Height;
  273.  
  274.     if(Info -> WindowFlags & WC_EXPANDWIDTH)
  275.         *Width = WindowWidth;
  276.  
  277.     if(Info -> WindowFlags & WC_EXPANDHEIGHT)
  278.         *Height = WindowHeight;
  279.  
  280.     Permit();
  281. }
  282.  
  283.     /* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
  284.      *
  285.      *    Get screen DPI resolution values.
  286.      */
  287.  
  288. VOID __regargs
  289. GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
  290. {
  291.     struct DisplayInfo DisplayInfo;
  292.  
  293.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
  294.     {
  295.         *X_DPI = (35 * 140) / DisplayInfo . PixelSpeed;
  296.         *Y_DPI = (*X_DPI * DisplayInfo . Resolution . x) / DisplayInfo . Resolution . y;
  297.     }
  298.     else
  299.         *X_DPI = *Y_DPI = 72;
  300. }
  301.  
  302.     /* AddProtection(STRPTR FileName,ULONG Mask):
  303.      *
  304.      *    Set bits in the protection mask of a file.
  305.      */
  306.  
  307. VOID __regargs
  308. AddProtection(STRPTR Name,ULONG Mask)
  309. {
  310.     struct FileInfoBlock *FileInfo;
  311.  
  312.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  313.     {
  314.         BPTR FileLock;
  315.  
  316.         if(FileLock = Lock(Name,ACCESS_READ))
  317.         {
  318.             if(Examine(FileLock,FileInfo))
  319.             {
  320.                 UnLock(FileLock);
  321.  
  322.                 SetProtection(Name,FileInfo -> fib_Protection | Mask);
  323.             }
  324.             else
  325.                 UnLock(FileLock);
  326.         }
  327.  
  328.         FreeDosObject(DOS_FIB,FileInfo);
  329.     }
  330. }
  331.  
  332.     /* GetPubScreenName(struct Screen *Screen,STRPTR Name):
  333.      *
  334.      *    Get the name of a public screen.
  335.      */
  336.  
  337. BYTE __regargs
  338. GetPubScreenName(struct Screen *Screen,STRPTR Name)
  339. {
  340.     struct List        *PubScreenList;
  341.     struct PubScreenNode    *ScreenNode;
  342.  
  343.     PubScreenList = LockPubScreenList();
  344.  
  345.     for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ)
  346.     {
  347.         if(ScreenNode -> psn_Screen == Screen)
  348.         {
  349.             strcpy(Name,ScreenNode -> psn_Node . ln_Name);
  350.  
  351.             UnlockPubScreenList();
  352.  
  353.             return(TRUE);
  354.         }
  355.     }
  356.  
  357.     UnlockPubScreenList();
  358.  
  359.     return(FALSE);
  360. }
  361.  
  362.     /* InitSinglePort(struct MsgPort *Port):
  363.      *
  364.      *    Initialize a plain MsgPort (as created on the stack) for
  365.      *    usage. Don't try this at home, kids!
  366.      */
  367.  
  368. VOID __regargs
  369. InitSinglePort(struct MsgPort *Port)
  370. {
  371.     memset(Port,0,sizeof(struct MsgPort));
  372.  
  373.     Port -> mp_Flags    = PA_SIGNAL;
  374.     Port -> mp_SigBit    = SIGB_SINGLE;
  375.     Port -> mp_SigTask    = SysBase -> ThisTask;
  376.  
  377.     NewList(&Port -> mp_MsgList);
  378. }
  379.  
  380.     /* GoodStream(BPTR Stream):
  381.      *
  382.      *    Check to see whether the current input file
  383.      *    is an interactive stream.
  384.      */
  385.  
  386. BYTE __regargs
  387. GoodStream(BPTR Stream)
  388. {
  389.     if(!Stream)
  390.     {
  391.         struct Process *ThisProcess = (struct Process *)SysBase -> ThisTask;
  392.  
  393.         Stream = ThisProcess -> pr_CIS;
  394.     }
  395.  
  396.     if(Stream)
  397.     {
  398.         struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  399.  
  400.         if(Handle -> fh_Type)
  401.         {
  402.             if(IsInteractive(Stream))
  403.                 return(TRUE);
  404.         }
  405.     }
  406.  
  407.     return(FALSE);
  408. }
  409.  
  410.     /* GetProgramIcon():
  411.      *
  412.      *    Try to find the icon of the program.
  413.      */
  414.  
  415. struct DiskObject *
  416. GetProgramIcon()
  417. {
  418.     struct DiskObject *Icon = NULL;
  419.  
  420.         /* Run from Workbench? */
  421.  
  422.     if(WBenchMsg)
  423.     {
  424.             /* Sanity check. */
  425.  
  426.         if(WBenchMsg -> sm_ArgList)
  427.         {
  428.                 /* Yet another sanity check. */
  429.  
  430.             if(WBenchMsg -> sm_ArgList -> wa_Name)
  431.             {
  432.                     /* Try to find the icon in the current directory. */
  433.  
  434.                 if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  435.                 {
  436.                     if(Icon -> do_Type != WBTOOL)
  437.                     {
  438.                         FreeDiskObject(Icon);
  439.  
  440.                         Icon = NULL;
  441.                     }
  442.                 }
  443.  
  444.                 if(!Icon)
  445.                 {
  446.                     BPTR NewLock;
  447.  
  448.                         /* Move to the directory the
  449.                          * program was run from.
  450.                          */
  451.  
  452.                     if(NewLock = Lock("PROGDIR:",ACCESS_READ))
  453.                     {
  454.                         BPTR OldLock;
  455.  
  456.                         OldLock = CurrentDir(NewLock);
  457.  
  458.                             /* Try to fetch the icon, use the
  459.                              * default name if necessary.
  460.                              */
  461.  
  462.                         if(Icon = GetDiskObjectNew(WBenchMsg -> sm_ArgList -> wa_Name))
  463.                         {
  464.                             if(Icon -> do_Type != WBTOOL)
  465.                             {
  466.                                 FreeDiskObject(Icon);
  467.  
  468.                                 Icon = NULL;
  469.                             }
  470.                         }
  471.  
  472.                         if(!Icon)
  473.                         {
  474.                             if(Icon = GetDiskObjectNew("term"))
  475.                             {
  476.                                 if(Icon -> do_Type != WBTOOL)
  477.                                 {
  478.                                     FreeDiskObject(Icon);
  479.  
  480.                                     Icon = NULL;
  481.                                 }
  482.                             }
  483.                         }
  484.  
  485.                         CurrentDir(OldLock);
  486.  
  487.                         UnLock(NewLock);
  488.                     }
  489.                 }
  490.             }
  491.         }
  492.     }
  493.  
  494.         /* Still no success. */
  495.  
  496.     if(!Icon)
  497.     {
  498.             /* Use the default names. */
  499.  
  500.         if(Icon = GetDiskObjectNew("term"))
  501.         {
  502.             if(Icon -> do_Type != WBTOOL)
  503.             {
  504.                 FreeDiskObject(Icon);
  505.  
  506.                 Icon = NULL;
  507.             }
  508.         }
  509.  
  510.         if(!Icon)
  511.         {
  512.             if(Icon = GetDiskObjectNew("PROGDIR:term"))
  513.             {
  514.                 if(Icon -> do_Type != WBTOOL)
  515.                 {
  516.                     FreeDiskObject(Icon);
  517.  
  518.                     Icon = NULL;
  519.                 }
  520.             }
  521.         }
  522.     }
  523.  
  524.     return(Icon);
  525. }
  526.  
  527.     /* GetPenIndex(LONG Pen):
  528.      *
  529.      *    Get the table index corresponding to an on-screen
  530.      *    text rendering pen.
  531.      */
  532.  
  533. LONG __regargs
  534. GetPenIndex(LONG Pen)
  535. {
  536.     LONG i;
  537.  
  538.     for(i = 0 ; i < 16 ; i++)
  539.     {
  540.         if(MappedPens[0][i] == Pen)
  541.             return(i);
  542.     }
  543. }
  544.  
  545.     /* GetScreenWidth(struct Window *Window):
  546.      *
  547.      *    Query the current screen width.
  548.      */
  549.  
  550. LONG __regargs
  551. GetScreenWidth(struct Window *Window)
  552. {
  553.     if(Window)
  554.     {
  555.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  556.             return(ScreenWidth);
  557.         else
  558.             return(Window -> Width - (Window -> BorderLeft + Window -> BorderRight));
  559.     }
  560.     else
  561.         return(ScreenWidth);
  562. }
  563.  
  564.     /* GetScreenHeight(struct Window *Window):
  565.      *
  566.      *    Query the current screen height.
  567.      */
  568.  
  569. LONG __regargs
  570. GetScreenHeight(struct Window *Window)
  571. {
  572.     if(Window)
  573.     {
  574.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  575.             return(ScreenHeight);
  576.         else
  577.             return(Window -> Height - (Window -> BorderTop + Window -> BorderBottom));
  578.     }
  579.     else
  580.         return(ScreenHeight);
  581. }
  582.  
  583.     /* GetLeft(struct Screen *Screen):
  584.      *
  585.      *    Get the screen left edge.
  586.      */
  587.  
  588. STATIC LONG __regargs
  589. GetLeft(struct Screen *Screen)
  590. {
  591.     if(Screen -> LeftEdge >= 0)
  592.         return(0);
  593.     else
  594.         return(-Screen -> LeftEdge);
  595. }
  596.  
  597.     /* GetScreenLeft(struct Window *Window):
  598.      *
  599.      *    Query the current screen left edge.
  600.      */
  601.  
  602. LONG __regargs
  603. GetScreenLeft(struct Window *Window)
  604. {
  605.     if(Window)
  606.     {
  607.         if(Window -> Width > ScreenWidth || Window -> LeftEdge < -Window -> WScreen -> LeftEdge || Window -> LeftEdge + Window -> WScreen -> LeftEdge + Window -> Width > ScreenWidth)
  608.             return(GetLeft(Window -> WScreen));
  609.         else
  610.             return(Window -> LeftEdge + Window -> BorderLeft);
  611.     }
  612.     else
  613.         return(GetLeft(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  614. }
  615.  
  616.     /* GetTop(struct Screen *Screen):
  617.      *
  618.      *    Get the screen top edge.
  619.      */
  620.  
  621. STATIC LONG __regargs
  622. GetTop(struct Screen *Screen)
  623. {
  624.     if(Screen -> TopEdge >= 0)
  625.         return(0);
  626.     else
  627.         return(-Screen -> TopEdge);
  628. }
  629.  
  630.     /* GetScreenTop(struct Window *Window):
  631.      *
  632.      *    Query the current screen top edge.
  633.      */
  634.  
  635. LONG __regargs
  636. GetScreenTop(struct Window *Window)
  637. {
  638.     if(Window)
  639.     {
  640.         if(Window -> Height > ScreenHeight || Window -> TopEdge < -Window -> WScreen -> TopEdge || Window -> TopEdge + Window -> WScreen -> TopEdge + Window -> Height > ScreenHeight)
  641.             return(GetTop(Window -> WScreen));
  642.         else
  643.             return(Window -> TopEdge + Window -> BorderTop);
  644.     }
  645.     else
  646.         return(GetTop(DefaultPubScreen ? DefaultPubScreen : SharedScreen));
  647. }
  648.  
  649.     /* OldGetAPen(struct RastPort *RPort):
  650.      *
  651.      *    Query the current primary rendering colour (old style).
  652.      */
  653.  
  654. ULONG 
  655. OldGetAPen(struct RastPort *RPort)
  656. {
  657.     return((ULONG)RPort -> FgPen);
  658. }
  659.  
  660.     /* OldGetBPen(struct RastPort *RPort):
  661.      *
  662.      *    Query the current seconary rendering colour (old style).
  663.      */
  664.  
  665. ULONG 
  666. OldGetBPen(struct RastPort *RPort)
  667. {
  668.     return((ULONG)RPort -> BgPen);
  669. }
  670.  
  671.     /* OldGetDrMd(struct RastPort *RPort):
  672.      *
  673.      *    Query the current drawing mode (old style).
  674.      */
  675.  
  676. ULONG 
  677. OldGetDrMd(struct RastPort *RPort)
  678. {
  679.     return((ULONG)RPort -> DrawMode);
  680. }
  681.  
  682.     /* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
  683.      *
  684.      *    Set the rendering plane mask (old style).
  685.      */
  686.  
  687. ULONG 
  688. OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
  689. {
  690.     RPort -> Mask = Mask;
  691.  
  692.     return((ULONG)1);
  693. }
  694.  
  695.     /* NewGetAPen(struct RastPort *RPort):
  696.      *
  697.      *    Query the current primary rendering colour (new style).
  698.      */
  699.  
  700. ULONG 
  701. NewGetAPen(struct RastPort *RPort)
  702. {
  703.     return(GetAPen(RPort));
  704. }
  705.  
  706.     /* NewGetBPen(struct RastPort *RPort):
  707.      *
  708.      *    Query the current seconary rendering colour (new style).
  709.      */
  710.  
  711. ULONG 
  712. NewGetBPen(struct RastPort *RPort)
  713. {
  714.     return(GetBPen(RPort));
  715. }
  716.  
  717.     /* NewGetDrMd(struct RastPort *RPort):
  718.      *
  719.      *    Query the current drawing mode (new style).
  720.      */
  721.  
  722. ULONG 
  723. NewGetDrMd(struct RastPort *RPort)
  724. {
  725.     return(GetDrMd(RPort));
  726. }
  727.  
  728.     /* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
  729.      *
  730.      *    Set the rendering plane mask (new style).
  731.      */
  732.  
  733. ULONG 
  734. NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
  735. {
  736.     return(SetWriteMask(RPort,Mask));
  737. }
  738.  
  739.     /* SetWait(struct Window *Window):
  740.      *
  741.      *    Set the busy wait mouse pointer.
  742.      */
  743.  
  744. VOID __regargs
  745. SetWait(struct Window *Window)
  746. {
  747.     if(Kick30)
  748.     {
  749.         SetWindowPointer(Window,
  750.             WA_BusyPointer,        TRUE,
  751.             WA_PointerDelay,    TRUE,
  752.         TAG_DONE);
  753.     }
  754.     else
  755.         SetPointer(Window,Stopwatch,16,16,-6,0);
  756. }
  757.  
  758.     /* ClrWait(struct Window *Window):
  759.      *
  760.      *    Remove the busy wait mouse pointer.
  761.      */
  762.  
  763. VOID __regargs
  764. ClrWait(struct Window *Window)
  765. {
  766.     if(Kick30)
  767.         SetWindowPointer(Window,TAG_DONE);
  768.     else
  769.         ClearPointer(Window);
  770. }
  771.  
  772.     /* GetModeName(ULONG Mode):
  773.      *
  774.      *    Get the name of a display mode.
  775.      */
  776.  
  777. STRPTR __regargs
  778. GetModeName(ULONG Mode)
  779. {
  780.     STATIC UBYTE __far    Buffer[DISPLAYNAMELEN + 1];
  781.     struct NameInfo        NameInfo;
  782.  
  783.     if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
  784.         strcpy(Buffer,NameInfo . Name);
  785.     else
  786.     {
  787.         struct DimensionInfo DimensionInfo;
  788.  
  789.         if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  790.         {
  791.             STRPTR MonitorName;
  792.  
  793.             switch(Mode & MONITOR_ID_MASK)
  794.             {
  795.                 case NTSC_MONITOR_ID:
  796.  
  797.                     MonitorName = "NTSC: ";
  798.                     break;
  799.  
  800.                 case PAL_MONITOR_ID:
  801.  
  802.                     MonitorName = "PAL: ";
  803.                     break;
  804.  
  805.                 case VGA_MONITOR_ID:
  806.  
  807.                     MonitorName = "VGA: ";
  808.                     break;
  809.  
  810.                 case A2024_MONITOR_ID:
  811.  
  812.                     MonitorName = "A2024: ";
  813.                     break;
  814.  
  815.                 default:
  816.  
  817.                     MonitorName = "";
  818.                     break;
  819.             }
  820.  
  821.             SPrintf(Buffer,"%s%ld × %ld",MonitorName,DimensionInfo . TxtOScan . MaxX - DimensionInfo . TxtOScan . MinX + 1,DimensionInfo . TxtOScan . MaxY - DimensionInfo . TxtOScan . MinY + 1);
  822.         }
  823.         else
  824.             strcpy(Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
  825.     }
  826.  
  827.     return(Buffer);
  828. }
  829.  
  830.     /* ModeOkay(ULONG ID):
  831.      *
  832.      *    Checks whether a display mode ID will do for deep
  833.      *    screen bitmaps.
  834.      */
  835.  
  836. BYTE __regargs
  837. ModeOkay(ULONG ID)
  838. {
  839.     struct DimensionInfo DimensionInfo;
  840.  
  841.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  842.     {
  843.         if(DimensionInfo . MaxDepth >= 4)
  844.             return(TRUE);
  845.     }
  846.  
  847.     return(FALSE);
  848. }
  849.  
  850.     /* SetClipMenu(BYTE Mode):
  851.      *
  852.      *    Enable/disable the copy/clear selection menu items.
  853.      */
  854.  
  855. VOID __regargs
  856. SetClipMenu(BYTE Mode)
  857. {
  858.     if(Mode && RasterEnabled)
  859.     {
  860.         OnItem(MEN_COPY);
  861.         OnItem(MEN_CLEAR);
  862.     }
  863.     else
  864.     {
  865.         OffItem(MEN_COPY);
  866.         OffItem(MEN_CLEAR);
  867.     }
  868. }
  869.  
  870.     /* SetRedialMenu():
  871.      *
  872.      *    Make the `redial' menu item available or make it
  873.      *    unavailable.
  874.      */
  875.  
  876. VOID
  877. SetRedialMenu()
  878. {
  879.     BYTE Mode;
  880.  
  881.     if(DialList)
  882.     {
  883.         if(DialList -> lh_Head -> ln_Succ)
  884.             Mode = TRUE;
  885.         else
  886.             Mode = FALSE;
  887.     }
  888.     else
  889.         Mode = FALSE;
  890.  
  891.     if(Mode && DialItemsAvailable)
  892.         OnItem(MEN_REDIAL);
  893.     else
  894.         OffItem(MEN_REDIAL);
  895. }
  896.  
  897.     /* SetDialMenu(BYTE Mode):
  898.      *
  899.      *    Block or enable the dialing menu.
  900.      */
  901.  
  902. VOID __regargs
  903. SetDialMenu(BYTE Mode)
  904. {
  905.     if(Window && Menu)
  906.     {
  907.         if(Mode)
  908.         {
  909.             if(DialList)
  910.             {
  911.                 if(DialList -> lh_Head -> ln_Succ)
  912.                     OnItem(MEN_REDIAL);
  913.                 else
  914.                     OffItem(MEN_REDIAL);
  915.             }
  916.             else
  917.                 OffItem(MEN_REDIAL);
  918.  
  919.             OnItem(MEN_DIAL_NUMBER);
  920.         }
  921.         else
  922.         {
  923.             OffItem(MEN_REDIAL);
  924.             OffItem(MEN_DIAL_NUMBER);
  925.         }
  926.  
  927.         DialItemsAvailable = Mode;
  928.     }
  929. }
  930.  
  931.     /* SetTransferMenu(BYTE Mode):
  932.      *
  933.      *    Block or enable the transfer menu.
  934.      */
  935.  
  936. VOID __regargs
  937. SetTransferMenu(BYTE Mode)
  938. {
  939.     if(Window && Menu)
  940.     {
  941.         if(Mode)
  942.         {
  943.             ULONG i;
  944.  
  945.             for(i = MEN_UPLOAD_ASCII ; i <= MEN_DOWNLOAD_BINARY ; i++)
  946.                 OnItem(i);
  947.  
  948.             OnItem(MEN_TRANSFER);
  949.         }
  950.         else
  951.         {
  952.             if(!Config -> TransferConfig -> ASCIIUploadLibrary[0])
  953.                 OffItem(MEN_UPLOAD_ASCII);
  954.             else
  955.                 OnItem(MEN_UPLOAD_ASCII);
  956.  
  957.             if(!Config -> TransferConfig -> ASCIIDownloadLibrary[0])
  958.                 OffItem(MEN_DOWNLOAD_ASCII);
  959.             else
  960.                 OnItem(MEN_DOWNLOAD_ASCII);
  961.  
  962.             if(!Config -> TransferConfig -> TextUploadLibrary[0])
  963.             {
  964.                 OffItem(MEN_UPLOAD_TEXT);
  965.                 OffItem(MEN_EDIT_AND_UPLOAD_TEXT);
  966.             }
  967.             else
  968.             {
  969.                 OnItem(MEN_UPLOAD_TEXT);
  970.                 OnItem(MEN_EDIT_AND_UPLOAD_TEXT);
  971.             }
  972.  
  973.             if(!Config -> TransferConfig -> TextDownloadLibrary[0])
  974.                 OffItem(MEN_DOWNLOAD_TEXT);
  975.             else
  976.                 OnItem(MEN_DOWNLOAD_TEXT);
  977.  
  978.             if(!Config -> TransferConfig -> BinaryUploadLibrary[0])
  979.                 OffItem(MEN_UPLOAD_BINARY);
  980.             else
  981.                 OnItem(MEN_UPLOAD_BINARY);
  982.  
  983.             if(!Config -> TransferConfig -> BinaryDownloadLibrary[0])
  984.                 OffItem(MEN_DOWNLOAD_BINARY);
  985.             else
  986.                 OnItem(MEN_DOWNLOAD_BINARY);
  987.  
  988.             OffItem(MEN_TRANSFER);
  989.         }
  990.     }
  991. }
  992.  
  993.     /* SetRasterMenu(BYTE Mode):
  994.      *
  995.      *    Block or enable the menu entries associated with
  996.      *    functions to access the screen raster.
  997.      */
  998.  
  999. VOID __regargs
  1000. SetRasterMenu(BYTE Mode)
  1001. {
  1002.     if(Window && Menu)
  1003.     {
  1004.         if(Mode)
  1005.         {
  1006.             OnItem(MEN_SAVE_AS_TEXT);
  1007.             OnItem(MEN_PRINT_SCREEN);
  1008.         }
  1009.         else
  1010.         {
  1011.             OffItem(MEN_SAVE_AS_TEXT);
  1012.             OffItem(MEN_PRINT_SCREEN);
  1013.         }
  1014.     }
  1015. }
  1016.  
  1017.     /* PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced):
  1018.      *
  1019.      *    Pick a font using asl.library
  1020.      */
  1021.  
  1022. BYTE __regargs
  1023. PickFont(struct Window *Window,STRPTR Name,WORD *Points,BYTE MonoSpaced)
  1024. {
  1025.     struct FontRequester    *Requester;
  1026.     BYTE             Result = FALSE;
  1027.     LONG             Left    = 0,
  1028.                  Top    = 0,
  1029.                  Width    = 0,
  1030.                  Height    = 0;
  1031.  
  1032.     GetWindowInfo(WINDOW_FONT,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
  1033.  
  1034.     if(Requester = (struct FontRequester *)AllocAslRequestTags(ASL_FontRequest,
  1035.         ASL_Window,                    Window,
  1036.         ASL_LeftEdge,                    Left,
  1037.         ASL_TopEdge,                    Top,
  1038.         ASL_Width,                    Width,
  1039.         ASL_Height,                    Height,
  1040.         MonoSpaced ? ASL_FuncFlags : TAG_IGNORE,    FONF_FIXEDWIDTH,
  1041.     TAG_DONE))
  1042.     {
  1043.         if(AslRequestTags(Requester,
  1044.             ASL_FontName,    Name,
  1045.             ASL_FontHeight,    *Points,
  1046.         TAG_DONE))
  1047.         {
  1048.             PutWindowInfo(WINDOW_FONT,Requester -> fo_LeftEdge,Requester -> fo_TopEdge,Requester -> fo_Width,Requester -> fo_Height);
  1049.  
  1050.             strcpy(Name,Requester -> fo_Attr . ta_Name);
  1051.  
  1052.             *Points = Requester -> fo_Attr . ta_YSize;
  1053.  
  1054.             Result = TRUE;
  1055.         }
  1056.  
  1057.         FreeAslRequest(Requester);
  1058.     }
  1059.  
  1060.     return(Result);
  1061. }
  1062.  
  1063.     /* ExtractString():
  1064.      *
  1065.      *    Extracts a string from a list separated by `|' characters.
  1066.      */
  1067.  
  1068. STRPTR __regargs
  1069. ExtractString(STRPTR String,STRPTR Destination,BYTE ReturnEnd)
  1070. {
  1071.     STRPTR OldString;
  1072.  
  1073.     if(ReturnEnd)
  1074.         OldString = NULL;
  1075.     else
  1076.         OldString = String;
  1077.  
  1078.     while(*String)
  1079.     {
  1080.         if(*String == '|')
  1081.         {
  1082.             *Destination = 0;
  1083.  
  1084.             String++;
  1085.  
  1086.             if(*String)
  1087.                 return(String);
  1088.             else
  1089.                 return(OldString);
  1090.         }
  1091.         else
  1092.             *Destination++ = *String++;
  1093.     }
  1094.  
  1095.     *Destination = 0;
  1096.  
  1097.     return(OldString);
  1098. }
  1099.  
  1100.     /* GetListSize(struct List *List):
  1101.      *
  1102.      *    Determine the number of entries in a list.
  1103.      */
  1104.  
  1105. LONG __regargs
  1106. GetListSize(struct List *List)
  1107. {
  1108.     struct Node    *Node    = List -> lh_Head;
  1109.     LONG         i    = 0;
  1110.  
  1111.     while(Node -> ln_Succ)
  1112.     {
  1113.         i++;
  1114.  
  1115.         Node = Node -> ln_Succ;
  1116.     }
  1117.  
  1118.     return(i);
  1119. }
  1120.  
  1121.     /* GetListNode(LONG Offset,struct List *List):
  1122.      *
  1123.      *    Return the n-th Node entry in a standard exec list.
  1124.      */
  1125.  
  1126. struct Node * __regargs
  1127. GetListNode(LONG Offset,struct List *List)
  1128. {
  1129.     struct Node    *Node;
  1130.     LONG         i;
  1131.  
  1132.     Node = List -> lh_Head;
  1133.  
  1134.     for(i = 0 ; i < Offset ; i++)
  1135.     {
  1136.         if(!Node -> ln_Succ -> ln_Succ)
  1137.             return(NULL);
  1138.  
  1139.         Node = Node -> ln_Succ;
  1140.     }
  1141.  
  1142.     return(Node);
  1143. }
  1144.  
  1145.     /* CreateNode(STRPTR Name): 
  1146.      *
  1147.      *    Put a name string into a list node.
  1148.      */
  1149.  
  1150. struct Node * __regargs
  1151. CreateNode(STRPTR Name)
  1152. {
  1153.     struct Node *Node;
  1154.  
  1155.     if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY | MEMF_PUBLIC))
  1156.     {
  1157.         Node -> ln_Name = (STRPTR)(Node + 1);
  1158.  
  1159.         strcpy(Node -> ln_Name,Name);
  1160.     }
  1161.  
  1162.     return(Node);
  1163. }
  1164.  
  1165.     /* FreeNode(struct Node *Node):
  1166.      *
  1167.      *    Remove and deallocate a node.
  1168.      */
  1169.  
  1170. VOID __regargs
  1171. FreeNode(struct Node *Node)
  1172. {
  1173.     Remove(Node);
  1174.  
  1175.     FreeVecPooled(Node);
  1176. }
  1177.  
  1178.     /* FreeList(struct List *List):
  1179.      *
  1180.      *    Remove all nodes from the list
  1181.      *    and free them on the way.
  1182.      */
  1183.  
  1184. VOID __regargs
  1185. FreeList(struct List *List)
  1186. {
  1187.     struct Node *Node,*NextNode;
  1188.  
  1189.     Node = List -> lh_Head;
  1190.  
  1191.     while(NextNode = Node -> ln_Succ)
  1192.     {
  1193.         Remove(Node);
  1194.  
  1195.         FreeNode(Node);
  1196.  
  1197.         Node = NextNode;
  1198.     }
  1199. }
  1200.  
  1201.     /* GetNodeOffset(struct Node *Node,struct List *List):
  1202.      *
  1203.      *    Scan a list for a certain node and return
  1204.      *    its position.
  1205.      */
  1206.  
  1207. LONG __regargs
  1208. GetNodeOffset(struct Node *Node,struct List *List)
  1209. {
  1210.     struct Node    *ListNode;
  1211.     LONG         Offset = 0;
  1212.  
  1213.     ListNode = List -> lh_Head;
  1214.  
  1215.     while(ListNode -> ln_Succ)
  1216.     {
  1217.         if(Node == ListNode)
  1218.             return(Offset);
  1219.         else
  1220.         {
  1221.             Offset++;
  1222.  
  1223.             ListNode = ListNode -> ln_Succ;
  1224.         }
  1225.     }
  1226.  
  1227.     return(~0);
  1228. }
  1229.  
  1230.     /* MoveList(struct List *From,struct List *To):
  1231.      *
  1232.      *    Move the contents of a list to a different list.
  1233.      */
  1234.  
  1235. VOID __regargs
  1236. MoveList(struct List *From,struct List *To)
  1237. {
  1238.     struct Node *Node,*NextNode;
  1239.  
  1240.     Node = From -> lh_Head;
  1241.  
  1242.     while(NextNode = Node -> ln_Succ)
  1243.     {
  1244.         Remove(Node);
  1245.  
  1246.         AddTail(To,Node);
  1247.  
  1248.         Node = NextNode;
  1249.     }
  1250. }
  1251.  
  1252.     /* LogAction(STRPTR String,...):
  1253.      *
  1254.      *    Write an action to the default log file.
  1255.      */
  1256.  
  1257. VOID __stdargs
  1258. LogAction(STRPTR String,...)
  1259. {
  1260.     if(Config -> CaptureConfig -> LogActions && Config -> CaptureConfig -> LogFileName[0])
  1261.     {
  1262.         UBYTE    DummyBuffer[512];
  1263.         BPTR    File;
  1264.  
  1265.         va_list    VarArgs;
  1266.  
  1267.             /* Build a valid string. */
  1268.  
  1269.         va_start(VarArgs,String);
  1270.         VSPrintf(DummyBuffer,String,VarArgs);
  1271.         va_end(VarArgs);
  1272.  
  1273.             /* Does the log file already exist? */
  1274.  
  1275.         if(GetFileSize(Config -> CaptureConfig -> LogFileName))
  1276.         {
  1277.                 /* It does, let's append the data. */
  1278.  
  1279.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_READWRITE))
  1280.             {
  1281.                 if(Seek(File,0,OFFSET_END) == -1)
  1282.                 {
  1283.                     Close(File);
  1284.  
  1285.                     File = NULL;
  1286.                 }
  1287.             }
  1288.         }
  1289.         else
  1290.         {
  1291.                 /* Create a new file. */
  1292.  
  1293.             if(File = Open(Config -> CaptureConfig -> LogFileName,MODE_NEWFILE))
  1294.                 FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
  1295.         }
  1296.  
  1297.             /* The file is open, build the date/time string and
  1298.              * write the log action.
  1299.              */
  1300.  
  1301.         if(File)
  1302.         {
  1303.             UBYTE        DateBuffer[40],
  1304.                     TimeBuffer[40];
  1305.             struct DateTime    DateTime;
  1306.  
  1307.             DateStamp(&DateTime . dat_Stamp);
  1308.  
  1309.             DateTime . dat_Format    = FORMAT_DOS;
  1310.             DateTime . dat_Flags    = NULL;
  1311.             DateTime . dat_StrDay    = NULL;
  1312.             DateTime . dat_StrDate    = DateBuffer;
  1313.             DateTime . dat_StrTime    = TimeBuffer;
  1314.  
  1315.             if(DateToStr(&DateTime))
  1316.             {
  1317.                 StripSpaces(TimeBuffer);
  1318.  
  1319.                 FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
  1320.             }
  1321.  
  1322.                 /* Done! */
  1323.  
  1324.             Close(File);
  1325.         }
  1326.     }
  1327. }
  1328.  
  1329.     /* FlushMsg(struct Window *Window):
  1330.      *
  1331.      *    Cancel all pending messages of a window.
  1332.      */
  1333.  
  1334. VOID __regargs
  1335. FlushMsg(struct Window *Window)
  1336. {
  1337.     struct IntuiMessage *Massage;
  1338.  
  1339.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1340.         ReplyMsg(&Massage -> ExecMessage);
  1341. }
  1342.  
  1343.     /* GetString(STRPTR Prompt,STRPTR Buffer):
  1344.      *
  1345.      *    Get a string from the user, very much the same as xpr_gets,
  1346.      *    but also including the `Load File' gadget.
  1347.      */
  1348.  
  1349. BYTE __regargs
  1350. GetString(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR Prompt,STRPTR Buffer)
  1351. {
  1352.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1353.  
  1354.     struct LayoutHandle    *Handle;
  1355.     BYTE             Success = FALSE;
  1356.     UBYTE             LocalBuffer[256];
  1357.  
  1358.     if(MaxChars > 255)
  1359.     {
  1360.         CopyMem(Buffer,LocalBuffer,255);
  1361.  
  1362.         LocalBuffer[255] = 0;
  1363.  
  1364.         MaxChars = 255;
  1365.     }
  1366.     else
  1367.         strcpy(LocalBuffer,Buffer);
  1368.  
  1369.     if(!Prompt)
  1370.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1371.  
  1372.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1373.         LH_LocaleHook,    &LocaleHook,
  1374.     TAG_DONE))
  1375.     {
  1376.         struct Window *Window;
  1377.  
  1378.         LT_New(Handle,
  1379.             LA_Type,    VERTICAL_KIND,
  1380.         TAG_DONE);
  1381.         {
  1382.             LT_New(Handle,
  1383.                 LA_Type,    VERTICAL_KIND,
  1384.                 LA_LabelText,    Prompt,
  1385.             TAG_DONE);
  1386.             {
  1387.                 if(Password)
  1388.                 {
  1389.                     LT_New(Handle,
  1390.                         LA_Type,    PASSWORD_KIND,
  1391.                         LA_STRPTR,    LocalBuffer,
  1392.                         LA_ID,        GAD_STRING,
  1393.                         LA_Chars,    40,
  1394.                         GTST_MaxChars,    MaxChars,
  1395.                     TAG_DONE);
  1396.                 }
  1397.                 else
  1398.                 {
  1399.                     LT_New(Handle,
  1400.                         LA_Type,    STRING_KIND,
  1401.                         LA_STRPTR,    LocalBuffer,
  1402.                         LA_ID,        GAD_STRING,
  1403.                         LA_Chars,    60,
  1404.                         LAST_Picker,    LoadGadget,
  1405.                     TAG_DONE);
  1406.                 }
  1407.  
  1408.                 LT_EndGroup(Handle);
  1409.             }
  1410.  
  1411.             LT_New(Handle,
  1412.                 LA_Type,VERTICAL_KIND,
  1413.             TAG_DONE);
  1414.             {
  1415.                 LT_New(Handle,
  1416.                     LA_Type,    XBAR_KIND,
  1417.                     LAXB_FullSize,    TRUE,
  1418.                 TAG_DONE);
  1419.  
  1420.                 LT_EndGroup(Handle);
  1421.             }
  1422.  
  1423.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1424.                 LAGR_SameSize,    TRUE,
  1425.                 LAGR_Spread,    TRUE,
  1426.             TAG_DONE);
  1427.             {
  1428.                 LT_New(Handle,
  1429.                     LA_Type,    BUTTON_KIND,
  1430.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1431.                     LA_ID,        GAD_OK,
  1432.                     LABT_ReturnKey,    TRUE,
  1433.                     LABT_ExtraFat,    TRUE,
  1434.                 TAG_DONE);
  1435.  
  1436.                 LT_New(Handle,
  1437.                     LA_Type,    BUTTON_KIND,
  1438.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1439.                     LA_ID,        GAD_CANCEL,
  1440.                     LABT_EscKey,    TRUE,
  1441.                     LABT_ExtraFat,    TRUE,
  1442.                 TAG_DONE);
  1443.  
  1444.                 LT_EndGroup(Handle);
  1445.             }
  1446.         }
  1447.  
  1448.         if(Window = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1449.             LAWN_HelpHook,        &GuideHook,
  1450.             WA_DepthGadget,        TRUE,
  1451.             WA_CloseGadget,        TRUE,
  1452.             WA_DragBar,        TRUE,
  1453.             WA_RMBTrap,        TRUE,
  1454.             WA_Activate,        TRUE,
  1455.         TAG_DONE))
  1456.         {
  1457.             struct IntuiMessage    *Message;
  1458.             BOOLEAN             Done = FALSE;
  1459.             ULONG             MsgClass,
  1460.                          MsgQualifier;
  1461.             UWORD             MsgCode;
  1462.             struct Gadget        *MsgGadget;
  1463.  
  1464.             LT_Activate(Handle,GAD_STRING);
  1465.  
  1466.             PushWindow(Window);
  1467.  
  1468.             LT_ShowWindow(Handle,TRUE);
  1469.  
  1470.             do
  1471.             {
  1472.                 if(Wait(PORTMASK(Window -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1473.                     break;
  1474.  
  1475.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  1476.                 {
  1477.                     MsgClass    = Message -> Class;
  1478.                     MsgQualifier    = Message -> Qualifier;
  1479.                     MsgCode        = Message -> Code;
  1480.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1481.  
  1482.                     GT_ReplyIMsg(Message);
  1483.  
  1484.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1485.  
  1486.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1487.                         Done = TRUE;
  1488.  
  1489.                     if(MsgClass == IDCMP_GADGETUP)
  1490.                     {
  1491.                         switch(MsgGadget -> GadgetID)
  1492.                         {
  1493.                             case GAD_STRING:
  1494.  
  1495.                                 if(MsgCode == '\r')
  1496.                                 {
  1497.                                     strcpy(Buffer,LocalBuffer);
  1498.  
  1499.                                     Success = Done = TRUE;
  1500.  
  1501.                                     LT_PressButton(Handle,GAD_OK);
  1502.                                 }
  1503.  
  1504.                                 break;
  1505.  
  1506.                             case GAD_OK:
  1507.  
  1508.                                 strcpy(Buffer,LocalBuffer);
  1509.  
  1510.                                 Success = Done = TRUE;
  1511.                                 break;
  1512.  
  1513.                             case GAD_CANCEL:
  1514.  
  1515.                                 Done = TRUE;
  1516.                                 break;
  1517.                         }
  1518.                     }
  1519.  
  1520.                     if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget -> GadgetID == GAD_STRING)
  1521.                     {
  1522.                         UBYTE             DummyBuffer[MAX_FILENAME_LENGTH],
  1523.                                     *DummyChar;
  1524.                         struct FileRequester    *FileRequest;
  1525.  
  1526.                         LT_LockWindow(Window);
  1527.  
  1528.                         SplitFileName(LocalBuffer,&DummyChar,DummyBuffer);
  1529.  
  1530.                         if(FileRequest = GetFile(Window,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),DummyBuffer,DummyChar,DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  1531.                         {
  1532.                             LT_SetAttributes(Handle,GAD_STRING,GTST_String,DummyBuffer,TAG_DONE);
  1533.  
  1534.                             FreeAslRequest(FileRequest);
  1535.                         }
  1536.  
  1537.                         LT_UnlockWindow(Window);
  1538.                     }
  1539.                 }
  1540.             }
  1541.             while(!Done);
  1542.  
  1543.             PopWindow();
  1544.         }
  1545.  
  1546.         LT_DeleteHandle(Handle);
  1547.     }
  1548.  
  1549.     return(Success);
  1550. }
  1551.  
  1552.     /* WakeUp(struct Window *Window,WORD Sound):
  1553.      *
  1554.      *    Pop a window to the front and alert the user.
  1555.      */
  1556.  
  1557. VOID __regargs
  1558. WakeUp(struct Window *Window,WORD Sound)
  1559. {
  1560.     if(Window)
  1561.     {
  1562.         if(Config -> TerminalConfig -> AlertMode == ALERT_SCREEN || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1563.         {
  1564.             if(Window -> WScreen -> LeftEdge > 0)
  1565.             {
  1566.                 if(Window -> WScreen -> TopEdge > 0)
  1567.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,-Window -> WScreen -> TopEdge);
  1568.                 else
  1569.                     MoveScreen(Window -> WScreen,-Window -> WScreen -> LeftEdge,0);
  1570.             }
  1571.             else
  1572.             {
  1573.                 if(Window -> WScreen -> TopEdge > 0)
  1574.                     MoveScreen(Window -> WScreen,0,-Window -> WScreen -> TopEdge);
  1575.             }
  1576.  
  1577.             WindowToFront(Window);
  1578.  
  1579.             ScreenToFront(Window -> WScreen);
  1580.         }
  1581.     }
  1582.  
  1583.     if(Sound != SOUND_BELL || Config -> TerminalConfig -> AlertMode == ALERT_BEEP || Config -> TerminalConfig -> AlertMode == ALERT_BEEP_SCREEN)
  1584.         SoundPlay(Sound);
  1585. }
  1586.  
  1587.     /* TaskDestructor(struct DataMsg *Item):
  1588.      *
  1589.      *    Msg destructor for the routines below.
  1590.      */
  1591.  
  1592. STATIC VOID __stdargs
  1593. TaskDestructor(struct DataMsg *Item)
  1594. {
  1595.     Signal((struct Process *)Item -> Data,SIGF_SINGLE);
  1596. }
  1597.  
  1598.     /* AmigaDOSBackgroundServer(VOID):
  1599.      *
  1600.      *    Background process to handle tool execution.
  1601.      */
  1602.  
  1603. STATIC VOID __saveds
  1604. AmigaDOSBackgroundServer(VOID)
  1605. {
  1606.     BPTR         OldCOS,
  1607.              NewCOS = NULL;
  1608.     struct DataMsg     Msg;
  1609.     STRPTR         Command;
  1610.     struct Process    *Me;
  1611.  
  1612.         /* Look who we are. */
  1613.  
  1614.     Me = (struct Process *)SysBase -> ThisTask;
  1615.  
  1616.     Command = Me -> pr_Task . tc_UserData;
  1617.  
  1618.         /* Create console output stream, will be closed automagically on exit. */
  1619.  
  1620.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1621.     {
  1622.         if(NewCOS = Open("*",MODE_NEWFILE))
  1623.         {
  1624.             OldCOS = Me -> pr_COS;
  1625.  
  1626.             Me -> pr_COS = NewCOS;
  1627.         }
  1628.     }
  1629.  
  1630.     SystemTags(Command,
  1631.         SYS_UserShell,    TRUE,
  1632.     TAG_DONE);
  1633.  
  1634.     FreeVecPooled(Command);
  1635.  
  1636.     Forbid();
  1637.  
  1638.     InitMsgItem(&Msg,TaskDestructor);
  1639.  
  1640.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1641.     Msg . Data = (UBYTE *)Me;
  1642.  
  1643.     ClrSignal(SIG_HANDSHAKE);
  1644.  
  1645.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1646.  
  1647.     Wait(SIG_HANDSHAKE);
  1648.  
  1649.     if(NewCOS)
  1650.     {
  1651.         Me -> pr_COS = OldCOS;
  1652.  
  1653.         Close(NewCOS);
  1654.     }
  1655. }
  1656.  
  1657.     /* SendAmigaDOSCommand(STRPTR Name):
  1658.      *
  1659.      *    Let the current default Shell execute an AmigaDOS
  1660.      *    command. Block until the command has returned.
  1661.      */
  1662.  
  1663. VOID __regargs
  1664. SendAmigaDOSCommand(STRPTR Name)
  1665. {
  1666.     STRPTR NewName;
  1667.  
  1668.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1669.     {
  1670.         struct Process    *NewProcess;
  1671.         BPTR         Stream;
  1672.         STRPTR         NewWindowName;
  1673.  
  1674.         strcpy(NewName,Name);
  1675.  
  1676.         NewWindowName = NewName + strlen(NewName) + 1;
  1677.  
  1678.         BlockWindows();
  1679.  
  1680.         SetQueueDiscard(SpecialQueue,FALSE);
  1681.  
  1682.             /* Open the output file. */
  1683.  
  1684.         if(WindowName[0])
  1685.         {
  1686.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1687.  
  1688.             if(Window)
  1689.             {
  1690.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1691.                     LocalName[0] = 0;
  1692.             }
  1693.  
  1694.             if(LocalName[0])
  1695.             {
  1696.                 SPrintf(NewWindowName,WindowName,LocalName);
  1697.  
  1698.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  1699.             }
  1700.             else
  1701.                 Stream = Open(WindowName,MODE_NEWFILE);
  1702.         }
  1703.         else
  1704.             Stream = NULL;
  1705.  
  1706.         Forbid();
  1707.  
  1708.         if(Stream)
  1709.         {
  1710.             if(GoodStream(Stream))
  1711.             {
  1712.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1713.  
  1714.                 NewProcess = (struct Process *)CreateNewProcTags(
  1715.                     NP_Entry,    AmigaDOSBackgroundServer,
  1716.                     NP_Name,    "term AmigaDOS Background Process",
  1717.                     NP_Input,    Stream,
  1718.                     NP_Output,    NULL,
  1719.                     NP_Cli,        TRUE,
  1720.                     NP_ConsoleTask,    Handle -> fh_Type,
  1721.                     NP_StackSize,    16384,
  1722.                 TAG_END);
  1723.             }
  1724.             else
  1725.             {
  1726.                 NewProcess = (struct Process *)CreateNewProcTags(
  1727.                     NP_Entry,    AmigaDOSBackgroundServer,
  1728.                     NP_Name,    "term AmigaDOS Background Process",
  1729.                     NP_Output,    Stream,
  1730.                     NP_Cli,        TRUE,
  1731.                     NP_ConsoleTask,    NULL,
  1732.                     NP_StackSize,    16384,
  1733.                 TAG_END);
  1734.             }
  1735.         }
  1736.         else
  1737.         {
  1738.             NewProcess = (struct Process *)CreateNewProcTags(
  1739.                 NP_Entry,    AmigaDOSBackgroundServer,
  1740.                 NP_Name,    "term AmigaDOS Background Process",
  1741.                 NP_Cli,        TRUE,
  1742.                 NP_ConsoleTask,    NULL,
  1743.                 NP_StackSize,    16384,
  1744.             TAG_END);
  1745.         }
  1746.  
  1747.             /* Did we succeed in creating the process? */
  1748.  
  1749.         if(NewProcess)
  1750.         {
  1751.             CantQuit++;
  1752.  
  1753.             NewProcess -> pr_Task . tc_UserData = NewName;
  1754.  
  1755.             Permit();
  1756.         }
  1757.         else
  1758.         {
  1759.             Permit();
  1760.  
  1761.             if(Stream)
  1762.                 Close(Stream);
  1763.  
  1764.             FreeVecPooled(NewName);
  1765.  
  1766.             BumpWindow(Window);
  1767.  
  1768.             ReleaseWindows();
  1769.         }
  1770.     }
  1771. }
  1772.  
  1773.     /* RexxBackgroundServer():
  1774.      *
  1775.      *    The background process to handle the rexx
  1776.      *    massaging.
  1777.      */
  1778.  
  1779. STATIC VOID __saveds
  1780. RexxBackgroundServer(VOID)
  1781. {
  1782.     struct MsgPort     *RexxPort;
  1783.     BPTR         OldCOS,
  1784.              NewCOS = NULL;
  1785.     struct DataMsg     Msg;
  1786.     STRPTR         Command;
  1787.     struct Process    *Me;
  1788.  
  1789.         /* Look who we are. */
  1790.  
  1791.     Me = (struct Process *)SysBase -> ThisTask;
  1792.  
  1793.     Command = Me -> pr_Task . tc_UserData;
  1794.  
  1795.         /* Create console output stream, will be closed automagically on exit. */
  1796.  
  1797.     if(!Me -> pr_COS && Me -> pr_ConsoleTask)
  1798.     {
  1799.         if(NewCOS = Open("*",MODE_NEWFILE))
  1800.         {
  1801.             OldCOS = Me -> pr_COS;
  1802.  
  1803.             Me -> pr_COS = NewCOS;
  1804.         }
  1805.     }
  1806.  
  1807.     if(RexxPort = FindPort(RXSDIR))
  1808.     {
  1809.         struct MsgPort __aligned     ReplyPort;
  1810.         struct RexxMsg            *RexxMsg;
  1811.  
  1812.         InitSinglePort(&ReplyPort);
  1813.  
  1814.         if(RexxMsg = CreateRexxMsg(&ReplyPort,"term",RexxPortName))
  1815.         {
  1816.             if(RexxMsg -> rm_Args[0] = CreateArgstring(Command,strlen(Command)))
  1817.             {
  1818.                 RexxMsg -> rm_Action = RXCOMM;
  1819.  
  1820.                 Forbid();
  1821.  
  1822.                 ClrSignal(SIGF_SINGLE);
  1823.  
  1824.                 PutMsg(RexxPort,(struct Message *)RexxMsg);
  1825.  
  1826.                 WaitPort(&ReplyPort);
  1827.  
  1828.                 GetMsg(&ReplyPort);
  1829.  
  1830.                 Permit();
  1831.  
  1832.                     /* This doesn't look too
  1833.                      * good, does it?
  1834.                      */
  1835.  
  1836.                 if(RexxMsg -> rm_Result1 && Me -> pr_COS)
  1837.                     Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Command,RexxMsg -> rm_Result1,RexxMsg -> rm_Result2);
  1838.  
  1839.                 DeleteArgstring(RexxMsg -> rm_Args[0]);
  1840.             }
  1841.  
  1842.             DeleteRexxMsg(RexxMsg);
  1843.         }
  1844.     }
  1845.  
  1846.     FreeVecPooled(Command);
  1847.  
  1848.     Forbid();
  1849.  
  1850.     InitMsgItem(&Msg,TaskDestructor);
  1851.  
  1852.     Msg . Type = DATAMSGTYPE_COMMANDDONE;
  1853.     Msg . Data = (UBYTE *)Me;
  1854.  
  1855.     ClrSignal(SIG_HANDSHAKE);
  1856.  
  1857.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  1858.  
  1859.     Wait(SIG_HANDSHAKE);
  1860.  
  1861.     if(NewCOS)
  1862.     {
  1863.         Me -> pr_COS = OldCOS;
  1864.  
  1865.         Close(NewCOS);
  1866.     }
  1867. }
  1868.  
  1869.     /* SendARexxCommand(STRPTR Name):
  1870.      *
  1871.      *    Let the ARexx server execute a command (or a script
  1872.      *    file if necessary) and block until the command
  1873.      *    has returned.
  1874.      */
  1875.  
  1876. VOID __regargs
  1877. SendARexxCommand(STRPTR Name)
  1878. {
  1879.     STRPTR NewName;
  1880.  
  1881.     if(NewName = (STRPTR)AllocVecPooled(strlen(Name) + 1 + 256,MEMF_ANY))
  1882.     {
  1883.         struct Process    *NewProcess;
  1884.         BPTR         Stream;
  1885.         STRPTR         NewWindowName;
  1886.  
  1887.         strcpy(NewName,Name);
  1888.  
  1889.         NewWindowName = NewName + strlen(NewName) + 1;
  1890.  
  1891.         BlockWindows();
  1892.  
  1893.         SetQueueDiscard(SpecialQueue,FALSE);
  1894.  
  1895.             /* Open the output file. */
  1896.  
  1897.         if(WindowName[0])
  1898.         {
  1899.             UBYTE LocalName[MAXPUBSCREENNAME + 1];
  1900.  
  1901.             if(Window)
  1902.             {
  1903.                 if(!GetPubScreenName(Window -> WScreen,LocalName))
  1904.                     LocalName[0] = 0;
  1905.             }
  1906.  
  1907.             if(LocalName[0])
  1908.             {
  1909.                 SPrintf(NewWindowName,WindowName,LocalName);
  1910.  
  1911.                 Stream = Open(NewWindowName,MODE_NEWFILE);
  1912.             }
  1913.             else
  1914.                 Stream = Open(WindowName,MODE_NEWFILE);
  1915.         }
  1916.         else
  1917.             Stream = NULL;
  1918.  
  1919.         Forbid();
  1920.  
  1921.             /* Create the background process which will
  1922.              * handle all the messy rexx message sending
  1923.              * for us.
  1924.              */
  1925.  
  1926.         if(Stream)
  1927.         {
  1928.             if(GoodStream(Stream))
  1929.             {
  1930.                 struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
  1931.  
  1932.                 NewProcess = (struct Process *)CreateNewProcTags(
  1933.                     NP_Entry,    RexxBackgroundServer,
  1934.                     NP_Name,    "term ARexx Background Process",
  1935.                     NP_Input,    Stream,
  1936.                     NP_Output,    NULL,
  1937.                     NP_Cli,        TRUE,
  1938.                     NP_ConsoleTask,    Handle -> fh_Type,
  1939.                     NP_StackSize,    16384,
  1940.                 TAG_END);
  1941.             }
  1942.             else
  1943.             {
  1944.                 NewProcess = (struct Process *)CreateNewProcTags(
  1945.                     NP_Entry,    RexxBackgroundServer,
  1946.                     NP_Name,    "term ARexx Background Process",
  1947.                     NP_Output,    Stream,
  1948.                     NP_Cli,        TRUE,
  1949.                     NP_ConsoleTask,    NULL,
  1950.                     NP_StackSize,    16384,
  1951.                 TAG_END);
  1952.             }
  1953.         }
  1954.         else
  1955.         {
  1956.             NewProcess = (struct Process *)CreateNewProcTags(
  1957.                 NP_Entry,    RexxBackgroundServer,
  1958.                 NP_Name,    "term ARexx Background Process",
  1959.                 NP_Cli,        TRUE,
  1960.                 NP_ConsoleTask,    NULL,
  1961.                 NP_StackSize,    16384,
  1962.             TAG_END);
  1963.         }
  1964.  
  1965.             /* Did we succeed in creating the process? */
  1966.  
  1967.         if(NewProcess)
  1968.         {
  1969.             CantQuit++;
  1970.  
  1971.             NewProcess -> pr_Task . tc_UserData = NewName;
  1972.  
  1973.             Permit();
  1974.         }
  1975.         else
  1976.         {
  1977.             Permit();
  1978.  
  1979.             if(Stream)
  1980.                 Close(Stream);
  1981.  
  1982.             FreeVecPooled(NewName);
  1983.  
  1984.             BumpWindow(Window);
  1985.  
  1986.             ReleaseWindows();
  1987.         }
  1988.     }
  1989. }
  1990.  
  1991.     /* BlockWindows():
  1992.      *
  1993.      *    Block the main window and the status window (i.e. disable
  1994.      *    the menu and attach a wait pointer).
  1995.      */
  1996.  
  1997. VOID
  1998. BlockWindows()
  1999. {
  2000.     if(!(BlockNestCount++))
  2001.     {
  2002.         LT_LockWindow(Window);
  2003.         LT_LockWindow(StatusWindow);
  2004.         LT_LockWindow(FastWindow);
  2005.  
  2006.         WeAreBlocking = TRUE;
  2007.  
  2008.         SetQueueDiscard(SpecialQueue,TRUE);
  2009.  
  2010.         GhostCursor();
  2011.     }
  2012. }
  2013.  
  2014.     /* ReleaseWindows():
  2015.      *
  2016.      *    Reenable the menus and clear the wait pointer.
  2017.      */
  2018.  
  2019. VOID
  2020. ReleaseWindows()
  2021. {
  2022.     if(BlockNestCount == 1)
  2023.     {
  2024.         LT_UnlockWindow(Window);
  2025.         LT_UnlockWindow(StatusWindow);
  2026.         LT_UnlockWindow(FastWindow);
  2027.  
  2028.         WeAreBlocking = FALSE;
  2029.  
  2030.         SetQueueDiscard(SpecialQueue,FALSE);
  2031.  
  2032.         if(Window)
  2033.         {
  2034.             Forbid();
  2035.  
  2036.             if(Window -> Flags & WFLG_WINDOWACTIVE)
  2037.                 NormalCursor();
  2038.  
  2039.             Permit();
  2040.         }
  2041.     }
  2042.  
  2043.     if(BlockNestCount)
  2044.         BlockNestCount--;
  2045. }
  2046.  
  2047.     /* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
  2048.      *
  2049.      *    Read a few bytes from a file (à la gets).
  2050.      */
  2051.  
  2052. LONG __regargs
  2053. LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
  2054. {
  2055.     STATIC UBYTE __far    Data[1024];
  2056.     STATIC LONG        ReadIndex    = 0,
  2057.                 ReadLen        = 0;
  2058.  
  2059.     if(File)
  2060.     {
  2061.         LONG BytesRead = 0,i;
  2062.  
  2063.         for(i = 0 ; i < MaxChars ; i++)
  2064.         {
  2065.             if(ReadIndex >= ReadLen)
  2066.             {
  2067.                 ReadLen = Read(File,Data,1024);
  2068.  
  2069.                 ReadIndex = 0;
  2070.  
  2071.                 if(ReadLen <= 0)
  2072.                 {
  2073.                     Buffer[i] = 0;
  2074.  
  2075.                     return(BytesRead);
  2076.                 }
  2077.             }
  2078.  
  2079.             BytesRead++;
  2080.  
  2081.             if((Buffer[i] = Data[ReadIndex++]) == '\n')
  2082.             {
  2083.                 Buffer[i + 1] = 0;
  2084.  
  2085.                 return(BytesRead);
  2086.             }
  2087.         }
  2088.  
  2089.         return(BytesRead);
  2090.     }
  2091.     else
  2092.         ReadIndex = ReadLen = 0;
  2093. }
  2094.  
  2095.     /* GetBaudRate(STRPTR Buffer):
  2096.      *
  2097.      *    Calculate the baud rate contained in a connect string.
  2098.      */
  2099.  
  2100. LONG __regargs
  2101. GetBaudRate(STRPTR Buffer)
  2102. {
  2103.     LONG Rate,i,j;
  2104.  
  2105.     for(i = j = 0 ; i < strlen(Buffer) ; i++)
  2106.     {
  2107.         if(Buffer[i] == ' ')
  2108.             continue;
  2109.         else
  2110.         {
  2111.             if(Buffer[i] >= '0' && Buffer[i] <= '9')
  2112.                 SharedBuffer[j++] = Buffer[i];
  2113.             else
  2114.                 break;
  2115.         }
  2116.     }
  2117.  
  2118.     SharedBuffer[j] = 0;
  2119.  
  2120.     if(StrToLong(SharedBuffer,&Rate) > 0)
  2121.     {
  2122.         if(Rate > 0)
  2123.             return(Rate);
  2124.     }
  2125.  
  2126.     return(0);
  2127. }
  2128.  
  2129.     /* LookForIt(struct MenuItem *Item,ULONG ID):
  2130.      *
  2131.      *    Auxilary routine for FindThisItem(), scans
  2132.      *    menu item and sub item lists.
  2133.      */
  2134.  
  2135. STATIC struct MenuItem * __inline
  2136. LookForIt(struct MenuItem *Item,ULONG ID)
  2137. {
  2138.     while(Item)
  2139.     {
  2140.         if((ULONG)GTMENUITEM_USERDATA(Item) == ID)
  2141.             return(Item);
  2142.         else
  2143.         {
  2144.             if(Item -> SubItem)
  2145.             {
  2146.                 register struct MenuItem *TheItem;
  2147.  
  2148.                 if(TheItem = LookForIt(Item -> SubItem,ID))
  2149.                     return(TheItem);
  2150.             }
  2151.  
  2152.             Item = Item -> NextItem;
  2153.         }
  2154.     }
  2155.  
  2156.     return(NULL);
  2157. }
  2158.  
  2159.     /* FindThisItem(struct Menu *FirstMenu,ULONG MenuID):
  2160.      *
  2161.      *    Scan a menu for a menuitem associated with a
  2162.      *    menu ID.
  2163.      */
  2164.  
  2165. struct MenuItem * __regargs
  2166. FindThisItem(struct Menu *FirstMenu,ULONG MenuID)
  2167. {
  2168.     struct MenuItem *Item;
  2169.  
  2170.     while(FirstMenu)
  2171.     {
  2172.         if(Item = LookForIt(FirstMenu -> FirstItem,MenuID))
  2173.             return(Item);
  2174.         else
  2175.             FirstMenu = FirstMenu -> NextMenu;
  2176.     }
  2177.  
  2178.     return(NULL);
  2179. }
  2180.  
  2181.     /* GetItem(ULONG MenuID):
  2182.      *
  2183.      *    Get the checkmark state of a menu item.
  2184.      */
  2185.  
  2186. BYTE __regargs
  2187. GetItem(ULONG MenuID)
  2188. {
  2189.     if(Menu)
  2190.     {
  2191.         struct MenuItem *Item;
  2192.  
  2193.         if(Item = FindThisItem(Menu,MenuID))
  2194.         {
  2195.             if(Item -> Flags & CHECKED)
  2196.                 return(TRUE);
  2197.         }
  2198.     }
  2199.  
  2200.     return(FALSE);
  2201. }
  2202.  
  2203.     /* SetItem(ULONG MenuID,BYTE Mode):
  2204.      *
  2205.      *    Clear or set the checkmark or state of a menu item.
  2206.      */
  2207.  
  2208. VOID __regargs
  2209. SetItem(ULONG MenuID,BYTE Mode)
  2210. {
  2211.         /* Is the global pull-down menu available? */
  2212.  
  2213.     if(Menu)
  2214.     {
  2215.         struct MenuItem *Item;
  2216.  
  2217.             /* Try to find the menu item and change
  2218.              * the state of the checkmark.
  2219.              */
  2220.  
  2221.         if(Item = FindThisItem(Menu,MenuID))
  2222.         {
  2223.                 /* Remove the menu from the windows. */
  2224.  
  2225.             if(Window)
  2226.                 ClearMenuStrip(Window);
  2227.  
  2228.             if(StatusWindow)
  2229.                 ClearMenuStrip(StatusWindow);
  2230.  
  2231.             if(FastWindow)
  2232.                 ClearMenuStrip(FastWindow);
  2233.  
  2234.             switch(Mode)
  2235.             {
  2236.                 case SETITEM_SETCHECK:
  2237.  
  2238.                     Item -> Flags |= CHECKED;
  2239.                     break;
  2240.  
  2241.                 case SETITEM_CLRCHECK:
  2242.  
  2243.                     Item -> Flags &= ~CHECKED;
  2244.                     break;
  2245.  
  2246.                 case SETITEM_ON:
  2247.  
  2248.                     Item -> Flags |= ITEMENABLED;
  2249.                     break;
  2250.  
  2251.                 case SETITEM_OFF:
  2252.  
  2253.                     Item -> Flags &= ~ITEMENABLED;
  2254.                     break;
  2255.             }
  2256.  
  2257.                 /* Reattach the menu to the windows. */
  2258.  
  2259.             if(Window)
  2260.                 ResetMenuStrip(Window,Menu);
  2261.  
  2262.             if(StatusWindow)
  2263.                 ResetMenuStrip(StatusWindow,Menu);
  2264.  
  2265.             if(FastWindow)
  2266.                 ResetMenuStrip(FastWindow,Menu);
  2267.         }
  2268.     }
  2269. }
  2270.  
  2271.     /* GetFileSize(STRPTR Name):
  2272.      *
  2273.      *    Simple routine to return the size of a file in
  2274.      *    bytes.
  2275.      */
  2276.  
  2277. LONG __regargs
  2278. GetFileSize(STRPTR Name)
  2279. {
  2280.     struct FileInfoBlock    *FileInfo;
  2281.     LONG             FileSize = 0;
  2282.  
  2283.     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2284.     {
  2285.         BPTR FileLock;
  2286.  
  2287.         if(FileLock = Lock(Name,ACCESS_READ))
  2288.         {
  2289.             if(Examine(FileLock,FileInfo))
  2290.             {
  2291.                 if(FileInfo -> fib_DirEntryType < 0)
  2292.                     FileSize = FileInfo -> fib_Size;
  2293.             }
  2294.  
  2295.             UnLock(FileLock);
  2296.         }
  2297.  
  2298.         FreeDosObject(DOS_FIB,FileInfo);
  2299.     }
  2300.  
  2301.     return(FileSize);
  2302. }
  2303.  
  2304.     /* GetFile(STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect):
  2305.      *
  2306.      *    Call the asl.library file requester to select a single or
  2307.      *    a couple of files.
  2308.      */
  2309.  
  2310. struct FileRequester * __regargs
  2311. GetFile(struct Window *Parent,STRPTR Title,STRPTR Directory,STRPTR Name,STRPTR Buffer,STRPTR Pattern,BYTE SaveFlag,BYTE MultiSelect,BYTE DirsOnly,STRPTR OKText,BYTE AskWrite)
  2312. {
  2313.     STATIC UBYTE __far     DirBuffer[MAX_FILENAME_LENGTH],
  2314.                  PatternBuffer[60];
  2315.  
  2316.     struct FileRequester    *AslFileRequest;
  2317.     BYTE             Result        = FALSE,
  2318.                  DefaultPattern    = FALSE;
  2319.     LONG             Flags,ExtFlags = 0;
  2320.     WORD             i,j;
  2321.  
  2322.     UBYTE             OtherTitle[60];
  2323.     LONG             Left    = 0,
  2324.                  Top    = 0,
  2325.                  Width    = 0,
  2326.                  Height    = 0;
  2327.  
  2328.     if(!Parent)
  2329.         Parent = Window;
  2330.  
  2331.     for(i = j = 0 ; i < strlen(Title) ; i++)
  2332.     {
  2333.         if(Title[i] != '_')
  2334.             OtherTitle[j++] = Title[i];
  2335.     }
  2336.  
  2337.     OtherTitle[j] = 0;
  2338.  
  2339.     Title = OtherTitle;
  2340.  
  2341.     if(DirsOnly)
  2342.     {
  2343.         ExtFlags |= FIL1F_NOFILES;
  2344.  
  2345.         if(Pattern)
  2346.             ExtFlags |= FIL1F_MATCHDIRS;
  2347.     }
  2348.  
  2349.     GetWindowInfo(WINDOW_FILE,&Left,&Top,&Width,&Height,Window -> Width / 2,Window -> Height / 2);
  2350.  
  2351.         /* Empty directory string? Revert to the last directory
  2352.          * name.
  2353.          */
  2354.  
  2355.     Forbid();
  2356.  
  2357.     if(!Directory[0])
  2358.     {
  2359.         if(!DirBuffer[0])
  2360.         {
  2361.             UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
  2362.  
  2363.             if(!GetCurrentDirName(LocalBuffer,MAX_FILENAME_LENGTH))
  2364.                 LocalBuffer[0] = 0;
  2365.  
  2366.             if(!DirBuffer[0])
  2367.                 strcpy(DirBuffer,LocalBuffer);
  2368.         }
  2369.  
  2370.         Directory = DirBuffer;
  2371.     }
  2372.  
  2373.         /* If a wildcard pattern is required, add a gadget
  2374.          * to display it.
  2375.          */
  2376.  
  2377.     if(Pattern)
  2378.     {
  2379.         Flags = FILF_PATGAD;
  2380.  
  2381.         if(!Pattern[0])
  2382.         {
  2383.             DefaultPattern = TRUE;
  2384.  
  2385.             if(PatternBuffer[0])
  2386.                 Pattern = PatternBuffer;
  2387.             else
  2388.                 Pattern = "#?";
  2389.         }
  2390.         else
  2391.         {
  2392.             if(!Stricmp(Pattern,"#?") || !Stricmp(Pattern,PatternBuffer))
  2393.             {
  2394.                 DefaultPattern = TRUE;
  2395.  
  2396.                 Pattern = PatternBuffer;
  2397.             }
  2398.         }
  2399.     }
  2400.     else
  2401.     {
  2402.         Flags = 0;
  2403.  
  2404.         Pattern = "#?";
  2405.     }
  2406.  
  2407.     Permit();
  2408.  
  2409.         /* Set the save flag if we are about to save something. */
  2410.  
  2411.     if(SaveFlag)
  2412.         Flags |= FILF_SAVE;
  2413.  
  2414.         /* Set the multiselect bit if multiple files are
  2415.          * to be selected (e.g. for batch file upload).
  2416.          */
  2417.  
  2418.     if(MultiSelect)
  2419.         Flags |= FILF_MULTISELECT;
  2420.  
  2421.         /* Provide a standard `Ok' text if none
  2422.          * specified.
  2423.          */
  2424.  
  2425.     if(!OKText)
  2426.         OKText = (SaveFlag ? LocaleString(MSG_GLOBAL_SAVE_TXT) : LocaleString(MSG_GLOBAL_OPEN_TXT));
  2427.  
  2428.         /* Allocate the asl.library directory requester
  2429.          * and display it.
  2430.          */
  2431.  
  2432.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  2433.         ASL_Window,    Parent,
  2434.         ASL_File,    Name,
  2435.         ASL_Dir,    Directory,
  2436.         Title ? ASL_Hail : TAG_IGNORE,    Title,
  2437.         ASL_FuncFlags,    Flags | FILF_NEWIDCMP,
  2438.         ASL_Pattern,    Pattern,
  2439.         ASL_OKText,    OKText,
  2440.         ASL_ExtFlags1,    ExtFlags,
  2441.         ASLFR_TextAttr,    &UserFont,
  2442.         ASL_LeftEdge,    Left,
  2443.         ASL_TopEdge,    Top,
  2444.         ASL_Width,    Width,
  2445.         ASL_Height,    Height,
  2446.     TAG_DONE))
  2447.     {
  2448.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  2449.         {
  2450.             PutWindowInfo(WINDOW_FILE,AslFileRequest -> rf_LeftEdge,AslFileRequest -> rf_TopEdge,AslFileRequest -> rf_Width,AslFileRequest -> rf_Height);
  2451.  
  2452.             if(!DirsOnly)
  2453.             {
  2454.                 STRPTR FileName;
  2455.  
  2456.                 if(AslFileRequest -> rf_NumArgs > 1 && AslFileRequest -> rf_ArgList)
  2457.                     FileName = AslFileRequest -> rf_ArgList -> wa_Name;
  2458.                 else
  2459.                     FileName = AslFileRequest -> rf_File;
  2460.  
  2461.                     /* Do we have a valid file name? */
  2462.  
  2463.                 if(FileName)
  2464.                 {
  2465.                         /* Build a legal path/file string. */
  2466.  
  2467.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2468.  
  2469.                     AddPart((STRPTR)Buffer,FileName,MAX_FILENAME_LENGTH);
  2470.  
  2471.                     Result = TRUE;
  2472.  
  2473.                     Forbid();
  2474.  
  2475.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2476.  
  2477.                     Permit();
  2478.                 }
  2479.             }
  2480.             else
  2481.             {
  2482.                 if(AslFileRequest -> rf_Dir[0])
  2483.                 {
  2484.                     strcpy(Buffer,AslFileRequest -> rf_Dir);
  2485.  
  2486.                     Result = TRUE;
  2487.  
  2488.                     Forbid();
  2489.  
  2490.                     strcpy(DirBuffer,AslFileRequest -> rf_Dir);
  2491.  
  2492.                     Permit();
  2493.                 }
  2494.             }
  2495.         }
  2496.     }
  2497.  
  2498.         /* We didn't get a file, no need to keep the
  2499.          * file requester.
  2500.          */
  2501.  
  2502.     if(!Result && AslFileRequest)
  2503.     {
  2504.         FreeAslRequest(AslFileRequest);
  2505.  
  2506.         return(NULL);
  2507.     }
  2508.     else
  2509.     {
  2510.         if(SaveFlag && AskWrite)
  2511.         {
  2512.             if(GetFileSize(Buffer))
  2513.             {
  2514.                 if(!MyEasyRequest(Parent,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_OVERWRITE_TXT),LocaleString(MSG_GLOBAL_REPLACE_CANCEL_TXT),FilePart(Buffer)))
  2515.                 {
  2516.                     FreeAslRequest(AslFileRequest);
  2517.  
  2518.                     return(NULL);
  2519.                 }
  2520.             }
  2521.         }
  2522.  
  2523.         Forbid();
  2524.  
  2525.         if(DefaultPattern)
  2526.             strcpy(PatternBuffer,AslFileRequest -> rf_Pat);
  2527.  
  2528.         Permit();
  2529.  
  2530.         return(AslFileRequest);
  2531.     }
  2532. }
  2533.  
  2534.     /* MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
  2535.      *
  2536.      *    Really quite simple varargs version of Intuition's
  2537.      *    EasyRequest requester.
  2538.      */
  2539.  
  2540. WORD __stdargs
  2541. MyEasyRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
  2542. {
  2543.     struct EasyStruct    Easy;
  2544.     WORD            Result;
  2545.     va_list             VarArgs;
  2546.  
  2547.         /* Standard data. */
  2548.  
  2549.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  2550.     Easy . es_Flags        = NULL;
  2551.     Easy . es_Title        = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
  2552.     Easy . es_TextFormat    = Text;
  2553.     Easy . es_GadgetFormat    = Gadgets;
  2554.  
  2555.         /* Use the argument array to build the
  2556.          * requester and display it.
  2557.          */
  2558.  
  2559.     va_start(VarArgs,Gadgets);
  2560.     Result = EasyRequestArgs(Window,&Easy,NULL,VarArgs);
  2561.     va_end(VarArgs);
  2562.  
  2563.     return(Result);
  2564. }
  2565.  
  2566.     /* SelectTime():
  2567.      *
  2568.      *    Searches for the correct unit/pay conversion values.
  2569.      */
  2570.  
  2571. VOID __regargs
  2572. SelectTime(struct PhoneEntry *SomeEntry)
  2573. {
  2574.     struct TimeDateNode        *TimeDateNode;
  2575.     struct DateStamp __aligned     Date;
  2576.     struct ClockData         ClockData;
  2577.     UBYTE                 Time;
  2578.     BYTE                 FoundOne = FALSE;
  2579.     LONG                 i,Last;
  2580.  
  2581.         /* Obtain current time and date. */
  2582.  
  2583.     DateStamp(&Date);
  2584.  
  2585.         /* Convert into a more suitable form (note: seconds are
  2586.          * required as an input value, ice is extra).
  2587.          */
  2588.  
  2589.     Amiga2Date(Date . ds_Days * 86400 + Date . ds_Minute * 60 + Date . ds_Tick / TICKS_PER_SECOND,&ClockData);
  2590.  
  2591.         /* Apparently, in the US of A the week starts with Sunday, we'll
  2592.          * wrap the week around to let it start with Monday.
  2593.          */
  2594.  
  2595.     if(ClockData . wday)
  2596.         ClockData . wday--;
  2597.     else
  2598.         ClockData . wday = 6;
  2599.  
  2600.         /* Change the month, too... */
  2601.  
  2602.     ClockData . month--;
  2603.  
  2604.         /* First step: search for current day. */
  2605.  
  2606.     TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2607.  
  2608.         /* Skip first entry. */
  2609.  
  2610.     TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2611.  
  2612.         /* First step: search for date settings. */
  2613.  
  2614.     while(TimeDateNode -> VanillaNode . ln_Succ)
  2615.     {
  2616.             /* Does it match a specific date? */
  2617.  
  2618.         if(TimeDateNode -> Header . Month == ClockData . month && TimeDateNode -> Header . Day == ClockData . mday)
  2619.         {
  2620.             FoundOne = TRUE;
  2621.  
  2622.             break;
  2623.         }
  2624.  
  2625.         TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2626.     }
  2627.  
  2628.         /* Second step: search for week day settings. */
  2629.  
  2630.     if(!FoundOne)
  2631.     {
  2632.         TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2633.  
  2634.             /* Skip first entry. */
  2635.  
  2636.         TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2637.  
  2638.         while(TimeDateNode -> VanillaNode . ln_Succ)
  2639.         {
  2640.                 /* Does it match a specific day? */
  2641.  
  2642.             if(TimeDateNode -> Header . Month == -1 && (TimeDateNode -> Header . Day & (1L << ClockData . wday)))
  2643.             {
  2644.                 FoundOne = TRUE;
  2645.  
  2646.                 break;
  2647.             }
  2648.  
  2649.             TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  2650.         }
  2651.     }
  2652.  
  2653.         /* Third step: use default settings. */
  2654.  
  2655.     if(!FoundOne)
  2656.         TimeDateNode = (struct TimeDateNode *)SomeEntry -> TimeDateList . mlh_Head;
  2657.  
  2658.         /* Convert current time to packed format. */
  2659.  
  2660.     Time = DT_GET_TIME(ClockData . hour,ClockData . min);
  2661.  
  2662.         /* Start with a blank. */
  2663.  
  2664.     Last = -1;
  2665.  
  2666.         /* Look for fitting time. */
  2667.  
  2668.     for(i = 0 ; i < TimeDateNode -> Table[0] . Count ; i++)
  2669.     {
  2670.             /* The time we are looking for must be >= the
  2671.              * current time.
  2672.              */
  2673.  
  2674.         if(TimeDateNode -> Table[i] . Time > Time)
  2675.         {
  2676.             if(i == 0)
  2677.                 break;
  2678.             else
  2679.             {
  2680.                 Last = i - 1;
  2681.                 break;
  2682.             }
  2683.         }
  2684.         else
  2685.             continue;
  2686.     }
  2687.  
  2688.         /* If none is found, take the last one in the list.
  2689.          * Note that this requires the list to be sorted in
  2690.          * ascending order.
  2691.          */
  2692.  
  2693.     if(Last == -1)
  2694.         Last = TimeDateNode -> Table[0] . Count - 1;
  2695.  
  2696.         /* Fill in the remaining data. */
  2697.  
  2698.     PayPerUnit[DT_FIRST_UNIT]    = TimeDateNode -> Table[Last] . PayPerUnit[DT_FIRST_UNIT];
  2699.     PayPerUnit[DT_NEXT_UNIT]    = TimeDateNode -> Table[Last] . PayPerUnit[DT_NEXT_UNIT];
  2700.     SecPerUnit[DT_FIRST_UNIT]    = TimeDateNode -> Table[Last] . SecPerUnit[DT_FIRST_UNIT];
  2701.     SecPerUnit[DT_NEXT_UNIT]    = TimeDateNode -> Table[Last] . SecPerUnit[DT_NEXT_UNIT];
  2702. }
  2703.  
  2704.     /* CloseWindowSafely(struct Window *Window):
  2705.      *
  2706.      *    Close a window freeing all messages pending at
  2707.      *    its user port (taken from example source code
  2708.      *    published once upon a time in Amiga Mail).
  2709.      */
  2710.  
  2711. VOID __regargs
  2712. CloseWindowSafely(struct Window *Window)
  2713. {
  2714.     struct IntuiMessage    *IntuiMessage;
  2715.     struct Node        *Successor;
  2716.  
  2717.     Forbid();
  2718.  
  2719.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  2720.  
  2721.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  2722.     {
  2723.         if(IntuiMessage -> IDCMPWindow == Window)
  2724.         {
  2725.             Remove(IntuiMessage);
  2726.  
  2727.             ReplyMsg((struct Message *)IntuiMessage);
  2728.         }
  2729.  
  2730.         IntuiMessage = (struct IntuiMessage *)Successor;
  2731.     }
  2732.  
  2733.     Window -> UserPort = NULL;
  2734.  
  2735.     ModifyIDCMP(Window,NULL);
  2736.  
  2737.     Permit();
  2738.  
  2739.     LT_DeleteWindowLock(Window);
  2740.  
  2741.     CloseWindow(Window);
  2742. }
  2743.  
  2744.     /* WaitTime(LONG Secs,LONG Micros):
  2745.      *
  2746.      *    Wait a given period of time.
  2747.      */
  2748.  
  2749. VOID __regargs
  2750. WaitTime(LONG Secs,LONG Micros)
  2751. {
  2752.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2753.     TimeRequest -> tr_time . tv_secs    = Secs;
  2754.     TimeRequest -> tr_time . tv_micro    = Micros;
  2755.  
  2756.     DoIO(TimeRequest);
  2757. }
  2758.  
  2759.     /* StopTime():
  2760.      *
  2761.      *    Stop the running timer.
  2762.      */
  2763.  
  2764. VOID
  2765. StopTime()
  2766. {
  2767.     if(TimerRunning)
  2768.     {
  2769.         if(!CheckIO(TimeRequest))
  2770.             AbortIO(TimeRequest);
  2771.  
  2772.         WaitIO(TimeRequest);
  2773.     }
  2774. }
  2775.  
  2776.     /* StartTime(LONG Secs,LONG Micros):
  2777.      *
  2778.      *    Start the timer asynchronously.
  2779.      */
  2780.  
  2781. VOID __regargs
  2782. StartTime(LONG Secs,LONG Micros)
  2783. {
  2784.     StopTime();
  2785.  
  2786.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2787.     TimeRequest -> tr_time . tv_secs    = Secs;
  2788.     TimeRequest -> tr_time . tv_micro    = Micros;
  2789.  
  2790.     ClrSignal(SIG_TIMER);
  2791.  
  2792.     SendIO(TimeRequest);
  2793.  
  2794.     TimerRunning = TRUE;
  2795. }
  2796.  
  2797.     /* GetEnvDOS(STRPTR Name,STRPTR Buffer):
  2798.      *
  2799.      *    Get the contents of a vanilla AmigaDOS environment
  2800.      *    variable.
  2801.      */
  2802.  
  2803. STRPTR __regargs
  2804. GetEnvDOS(STRPTR Name,STRPTR Buffer)
  2805. {
  2806.     LONG    Size;
  2807.     BPTR    File,SomeLock;
  2808.  
  2809.     Buffer[0] = 0;
  2810.  
  2811.         /* Is ENV: present? */
  2812.  
  2813.     if(SomeLock = Lock("Env:",ACCESS_READ))
  2814.     {
  2815.         UBYTE SomeBuffer[MAX_FILENAME_LENGTH];
  2816.  
  2817.         UnLock(SomeLock);
  2818.  
  2819.         strcpy(SomeBuffer,"Env:");
  2820.         strcat(SomeBuffer,Name);
  2821.  
  2822.             /* Open the file. */
  2823.  
  2824.         if(File = Open(SomeBuffer,MODE_OLDFILE))
  2825.         {
  2826.                 /* Read the contents. */
  2827.  
  2828.             Size = Read(File,Buffer,256);
  2829.  
  2830.             Close(File);
  2831.  
  2832.             if(Size > 0)
  2833.             {
  2834.                 Buffer[Size] = 0;
  2835.  
  2836.                 return(Buffer);
  2837.             }
  2838.         }
  2839.     }
  2840.  
  2841.     return(NULL);
  2842. }
  2843.  
  2844.     /* SetEnvDOS(STRPTR Name,STRPTR Value):
  2845.      *
  2846.      *    Set the contents of a vanilla AmigaDOS environment
  2847.      *    variable.
  2848.      */
  2849.  
  2850. BYTE __regargs
  2851. SetEnvDOS(STRPTR Name,STRPTR Value)
  2852. {
  2853.     UBYTE    Buffer[MAX_FILENAME_LENGTH],*Destination;
  2854.     LONG    Length;
  2855.     BPTR    File,FileLock;
  2856.     BYTE    Success = TRUE;
  2857.     WORD    i;
  2858.  
  2859.     for(i = 0 ; i < 2 ; i++)
  2860.     {
  2861.         if(i)
  2862.             Destination = "EnvArc:";
  2863.         else
  2864.             Destination = "Env:";
  2865.  
  2866.             /* Is ENV:/ENVARC: present? */
  2867.  
  2868.         if(FileLock = Lock(Destination,ACCESS_READ))
  2869.         {
  2870.             UnLock(FileLock);
  2871.  
  2872.             strcpy(Buffer,Destination);
  2873.             strcat(Buffer,Name);
  2874.  
  2875.                 /* There already is a variable of that
  2876.                  * name in the environment storage
  2877.                  * directory.
  2878.                  */
  2879.  
  2880.             if(FileLock = Lock(Buffer,ACCESS_WRITE))
  2881.             {
  2882.                 UnLock(FileLock);
  2883.  
  2884.                     /* Delete the variable. */
  2885.  
  2886.                 if(!DeleteFile(Buffer))
  2887.                 {
  2888.                     Success = FALSE;
  2889.  
  2890.                     continue;
  2891.                 }
  2892.             }
  2893.  
  2894.                 /* Set the new variable. */
  2895.  
  2896.             if(Length = strlen(Value))
  2897.             {
  2898.                 if(File = Open(Buffer,MODE_NEWFILE))
  2899.                 {
  2900.                     if(Write(File,Value,Length) != Length)
  2901.                     {
  2902.                         Close(File);
  2903.  
  2904.                         DeleteFile(Buffer);
  2905.  
  2906.                         Success = FALSE;
  2907.                     }
  2908.                     else
  2909.                     {
  2910.                         Close(File);
  2911.  
  2912.                         AddProtection(Buffer,FIBF_EXECUTE);
  2913.                     }
  2914.                 }
  2915.                 else
  2916.                     Success = FALSE;
  2917.             }
  2918.         }
  2919.         else
  2920.             Success = FALSE;
  2921.     }
  2922.  
  2923.     return(Success);
  2924. }
  2925.  
  2926.     /* BumpWindow(struct Window *SomeWindow):
  2927.      *
  2928.      *    Bring a window to the front (and shift the screen
  2929.      *    back to its initial position).
  2930.      */
  2931.  
  2932. VOID __regargs
  2933. BumpWindow(struct Window *SomeWindow)
  2934. {
  2935.     if(SomeWindow)
  2936.     {
  2937.         if(SomeWindow -> WScreen -> LeftEdge > 0)
  2938.         {
  2939.             if(SomeWindow -> WScreen -> TopEdge > 0)
  2940.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,-SomeWindow -> WScreen -> TopEdge);
  2941.             else
  2942.                 MoveScreen(SomeWindow -> WScreen,-SomeWindow -> WScreen -> LeftEdge,0);
  2943.         }
  2944.         else
  2945.         {
  2946.             if(SomeWindow -> WScreen -> TopEdge > 0)
  2947.                 MoveScreen(SomeWindow -> WScreen,0,-SomeWindow -> WScreen -> TopEdge);
  2948.         }
  2949.  
  2950.         ScreenToFront(SomeWindow -> WScreen);
  2951.  
  2952.         ActivateWindow(SomeWindow);
  2953.     }
  2954. }
  2955.  
  2956.     /* PushWindow(struct Window *Window):
  2957.      *
  2958.      *    Push/PopWindow implement a single lifo window stack
  2959.      *    which always updates the window to activate when
  2960.      *    LSHIFT+RSHIFT+RETURN is pressed. This routine will
  2961.      *    push a window on the stack.
  2962.      */
  2963.  
  2964. VOID __regargs
  2965. PushWindow(struct Window *Window)
  2966. {
  2967.     if(WindowStackPtr < 5)
  2968.     {
  2969.         WindowStack[WindowStackPtr++] = Window;
  2970.  
  2971.         TopWindow = Window;
  2972.     }
  2973. }
  2974.  
  2975.     /* PopWindow():
  2976.      *
  2977.      *    Remove topmost window from window stack.
  2978.      */
  2979.  
  2980. VOID
  2981. PopWindow()
  2982. {
  2983.     if(WindowStackPtr > 0)
  2984.     {
  2985.         WindowStackPtr--;
  2986.  
  2987.         if(WindowStackPtr)
  2988.             TopWindow = WindowStack[WindowStackPtr - 1];
  2989.         else
  2990.             TopWindow = Window;
  2991.     }
  2992. }
  2993.  
  2994.     /* LoadMacros(STRPTR Name,struct MacroKeys *Keys):
  2995.      *
  2996.      *    Load the keyboard macros from a file.
  2997.      */
  2998.  
  2999. BYTE __regargs
  3000. LoadMacros(STRPTR Name,struct MacroKeys *Keys)
  3001. {
  3002.     struct IFFHandle    *Handle;
  3003.     BYTE             Success = FALSE;
  3004.     struct StoredProperty    *Prop;
  3005.     struct TermInfo        *TermInfo;
  3006.     LONG             Error;
  3007.  
  3008.     if(Handle = AllocIFF())
  3009.     {
  3010.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3011.         {
  3012.             InitIFFasDOS(Handle);
  3013.  
  3014.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3015.             {
  3016.                 /* Collect version number ID if
  3017.                  * available.
  3018.                  */
  3019.  
  3020.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3021.                 {
  3022.                     /* The following line tells iffparse to stop at the
  3023.                      * very beginning of a `Type' chunk contained in a
  3024.                      * `TERM' FORM chunk.
  3025.                      */
  3026.  
  3027.                     if(!(Error = StopChunk(Handle,ID_TERM,ID_KEYS)))
  3028.                     {
  3029.                         /* Parse the file... */
  3030.  
  3031.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3032.                         {
  3033.                             /* Did we get a version ID? */
  3034.  
  3035.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3036.                             {
  3037.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3038.  
  3039.                                 /* Is it the file format we are able
  3040.                                  * to read?
  3041.                                  */
  3042.  
  3043.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3044.                                 {
  3045.                                         /* Probably an older revision. */
  3046.  
  3047.                                     if(TermInfo -> Version == 1 && TermInfo -> Revision < 6)
  3048.                                     {
  3049.                                         memset(Keys,0,sizeof(struct MacroKeys));
  3050.  
  3051.                                         if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3052.                                             Success = TRUE;
  3053.                                         else
  3054.                                             Error = IoErr();
  3055.                                     }
  3056.                                     else
  3057.                                         Error = ERR_OUTDATED;
  3058.                                 }
  3059.                                 else
  3060.                                 {
  3061.                                     /* The file read pointer is positioned
  3062.                                      * just in front of the first data
  3063.                                      * to be read, so let's don't disappoint
  3064.                                      * iffparse and read it.
  3065.                                      */
  3066.  
  3067.                                     if(ReadChunkBytes(Handle,Keys,sizeof(struct MacroKeys)) == sizeof(struct MacroKeys))
  3068.                                         Success = TRUE;
  3069.                                     else
  3070.                                         Error = IoErr();
  3071.                                 }
  3072.                             }
  3073.                             else
  3074.                             {
  3075.                                     /* File was created by WriteIFFData previous
  3076.                                      * to revision 1.4.
  3077.                                      */
  3078.  
  3079.                                 memset(Keys,0,sizeof(struct MacroKeys));
  3080.  
  3081.                                 if(ReadChunkBytes(Handle,Keys,10 * 256) == 10 * 256)
  3082.                                     Success = TRUE;
  3083.                                 else
  3084.                                     Error = IoErr();
  3085.                             }
  3086.                         }
  3087.                     }
  3088.                 }
  3089.  
  3090.                 CloseIFF(Handle);
  3091.             }
  3092.  
  3093.             Close(Handle -> iff_Stream);
  3094.         }
  3095.         else
  3096.             Error = IoErr();
  3097.  
  3098.         FreeIFF(Handle);
  3099.     }
  3100.     else
  3101.         Error = ERR_NO_MEM;
  3102.  
  3103.     if(Error)
  3104.         SetIoErr(Error);
  3105.  
  3106.     return(Success);
  3107. }
  3108.  
  3109.     /* WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3110.      *
  3111.      *    Write data to an IFF file (via iffparse.library).
  3112.      */
  3113.  
  3114. BYTE __regargs
  3115. WriteIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3116. {
  3117.     struct IFFHandle    *Handle;
  3118.     BYTE             Success = FALSE;
  3119.     LONG             Error;
  3120.  
  3121.         /* Allocate a handle. */
  3122.  
  3123.     if(Handle = AllocIFF())
  3124.     {
  3125.             /* Open an output stream. */
  3126.  
  3127.         if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  3128.         {
  3129.                 /* Tell iffparse that this is
  3130.                  * a DOS handle.
  3131.                  */
  3132.  
  3133.             InitIFFasDOS(Handle);
  3134.  
  3135.                 /* Open the handle for writing. */
  3136.  
  3137.             if(!(Error = OpenIFF(Handle,IFFF_WRITE)))
  3138.             {
  3139.                     /* Push outmost chunk onto stack. */
  3140.  
  3141.                 if(!(Error = PushChunk(Handle,ID_TERM,ID_FORM,IFFSIZE_UNKNOWN)))
  3142.                 {
  3143.                         /* Add a version identifier. */
  3144.  
  3145.                     if(!(Error = PushChunk(Handle,0,ID_VERS,IFFSIZE_UNKNOWN)))
  3146.                     {
  3147.                         struct TermInfo TermInfo;
  3148.  
  3149.                         TermInfo . Version    = TermVersion;
  3150.                         TermInfo . Revision    = TermRevision;
  3151.  
  3152.                             /* Write the version data. */
  3153.  
  3154.                         if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  3155.                         {
  3156.                                 /* Pop the version chunk, i.e. write it to the file. */
  3157.  
  3158.                             if(Error = PopChunk(Handle))
  3159.                                 Success = FALSE;
  3160.                             else
  3161.                             {
  3162.                                     /* Push the real data chunk on the stack. */
  3163.  
  3164.                                 if(!(Error = PushChunk(Handle,0,Type,IFFSIZE_UNKNOWN)))
  3165.                                 {
  3166.                                         /* Write the data. */
  3167.  
  3168.                                     if(WriteChunkBytes(Handle,Data,Size) == Size)
  3169.                                         Success = TRUE;
  3170.                                     else
  3171.                                         Error = IoErr();
  3172.  
  3173.                                             /* Pop the data chunk. */
  3174.  
  3175.                                     if(Success)
  3176.                                     {
  3177.                                         if(Error = PopChunk(Handle))
  3178.                                             Success = FALSE;
  3179.                                     }
  3180.                                 }
  3181.                                 else
  3182.                                     Success = FALSE;
  3183.                             }
  3184.                         }
  3185.                         else
  3186.                         {
  3187.                             Error = IoErr();
  3188.  
  3189.                             Success = FALSE;
  3190.                         }
  3191.                     }
  3192.  
  3193.                         /* Seems that we're done, now try to pop the FORM chunk
  3194.                          * and return.
  3195.                          */
  3196.  
  3197.                     if(Success)
  3198.                     {
  3199.                         if(Error = PopChunk(Handle))
  3200.                             Success = FALSE;
  3201.                     }
  3202.                 }
  3203.  
  3204.                     /* Close the handle (flush any pending data). */
  3205.  
  3206.                 CloseIFF(Handle);
  3207.             }
  3208.  
  3209.                 /* Close the DOS handle itself. */
  3210.  
  3211.             Close(Handle -> iff_Stream);
  3212.         }
  3213.         else
  3214.             Error = IoErr();
  3215.  
  3216.             /* And free the IFF handle. */
  3217.  
  3218.         FreeIFF(Handle);
  3219.     }
  3220.     else
  3221.         Error = ERR_NO_MEM;
  3222.  
  3223.     if(Success)
  3224.         AddProtection(Name,FIBF_EXECUTE);
  3225.  
  3226.     if(Error)
  3227.         SetIoErr(Error);
  3228.  
  3229.     return(Success);
  3230. }
  3231.  
  3232.     /* ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type):
  3233.      *
  3234.      *    Read data from a `TERM' FORM chunk contained in an IFF file.
  3235.      */
  3236.  
  3237. BYTE __regargs
  3238. ReadIFFData(STRPTR Name,APTR Data,LONG Size,ULONG Type)
  3239. {
  3240.     struct IFFHandle    *Handle;
  3241.     BYTE             Success = FALSE;
  3242.     struct StoredProperty    *Prop;
  3243.     struct TermInfo        *TermInfo;
  3244.     LONG             Error = 0;
  3245.  
  3246.     if(Handle = AllocIFF())
  3247.     {
  3248.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  3249.         {
  3250.             InitIFFasDOS(Handle);
  3251.  
  3252.             if(!(Error = OpenIFF(Handle,IFFF_READ)))
  3253.             {
  3254.                 /* Collect version number ID if
  3255.                  * available.
  3256.                  */
  3257.  
  3258.                 if(!(Error = PropChunks(Handle,(LONG *)VersionProps,1)))
  3259.                 {
  3260.                     /* The following line tells iffparse to stop at the
  3261.                      * very beginning of a `Type' chunk contained in a
  3262.                      * `TERM' FORM chunk.
  3263.                      */
  3264.  
  3265.                     if(!(Error = StopChunk(Handle,ID_TERM,Type)))
  3266.                     {
  3267.                         /* Parse the file... */
  3268.  
  3269.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  3270.                         {
  3271.                             /* Did we get a version ID? */
  3272.  
  3273.                             if(Prop = FindProp(Handle,ID_TERM,ID_VERS))
  3274.                             {
  3275.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  3276.  
  3277.                                 /* Is it the file format we are able
  3278.                                  * to read?
  3279.                                  */
  3280.  
  3281.                                 if((TermInfo -> Version > TermVersion) || (TermInfo -> Version == TermVersion && TermInfo -> Revision > TermRevision) || (TermInfo -> Version == 1 && TermInfo -> Revision < 6))
  3282.                                 {
  3283.                                     Error = ERR_OUTDATED;
  3284.  
  3285.                                     Success = FALSE;
  3286.                                 }
  3287.                                 else
  3288.                                 {
  3289.                                     struct ContextNode *Chunk = CurrentChunk(Handle);
  3290.  
  3291.                                     if(Chunk -> cn_Size < Size)
  3292.                                         Size = Chunk -> cn_Size;
  3293.  
  3294.                                     /* The file read pointer is positioned
  3295.                                      * just in front of the first data
  3296.                                      * to be read, so let's don't disappoint
  3297.                                      * iffparse and read it.
  3298.                                      */
  3299.  
  3300.                                     if(ReadChunkBytes(Handle,Data,Size) == Size)
  3301.                                         Success = TRUE;
  3302.                                     else
  3303.                                         Error = IoErr();
  3304.                                 }
  3305.                             }
  3306.                         }
  3307.                     }
  3308.                 }
  3309.  
  3310.                 CloseIFF(Handle);
  3311.             }
  3312.  
  3313.             Close(Handle -> iff_Stream);
  3314.         }
  3315.         else
  3316.             Error = IoErr();
  3317.  
  3318.         FreeIFF(Handle);
  3319.     }
  3320.  
  3321.     if(Error)
  3322.         SetIoErr(Error);
  3323.  
  3324.     return(Success);
  3325. }
  3326.  
  3327.     /* SplitFileName():
  3328.      *
  3329.      *    Split a full file name into a file and a drawer name.
  3330.      */
  3331.  
  3332. VOID __regargs
  3333. SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
  3334. {
  3335.     if(FilePart(FullName) == FullName)
  3336.     {
  3337.         *DrawerName    = 0;
  3338.         *FileName    = FullName;
  3339.     }
  3340.     else
  3341.     {
  3342.         STRPTR Dummy;
  3343.  
  3344.         strcpy(DrawerName,FullName);
  3345.  
  3346.         Dummy = PathPart(DrawerName);
  3347.  
  3348.         *Dummy = 0;
  3349.  
  3350.         *FileName = FilePart(FullName);
  3351.     }
  3352. }
  3353.  
  3354.     /* DeleteList():
  3355.      *
  3356.      *    Free the contents of a list and the list itself.
  3357.      */
  3358.  
  3359. VOID __regargs
  3360. DeleteList(struct List *List)
  3361. {
  3362.     if(List)
  3363.     {
  3364.         struct Node    *Node,
  3365.                 *Next;
  3366.  
  3367.         for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3368.             FreeVecPooled(Node);
  3369.  
  3370.         FreeVecPooled(List);
  3371.     }
  3372. }
  3373.  
  3374.     /* BackfillRoutine():
  3375.      *
  3376.      *    Window layer backfill routine.
  3377.      */
  3378.  
  3379. ULONG __asm __saveds
  3380. BackfillRoutine(register __a0 struct Hook *Hook,register __a1 struct {ULONG Layer; struct Rectangle Bounds;} *Bounds,register __a2 struct RastPort *RPort)
  3381. {
  3382.     struct RastPort RastPort = *RPort;
  3383.  
  3384.     RPort = &RastPort;
  3385.  
  3386.     RPort -> Layer = NULL;
  3387.  
  3388.     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  3389.     SetDrMd(RPort,JAM1);
  3390.  
  3391.     RectFill(RPort,Bounds -> Bounds . MinX,Bounds -> Bounds . MinY,Bounds -> Bounds . MaxX,Bounds -> Bounds . MaxY);
  3392.  
  3393.     return(TRUE);
  3394. }
  3395.  
  3396. struct NameSegment
  3397. {
  3398.     UBYTE    String[63],
  3399.         Separator;
  3400. };
  3401.  
  3402. STATIC UBYTE * __regargs
  3403. GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,WORD i)
  3404. {
  3405.     UBYTE *xp = NameSegment[i] . String;
  3406.  
  3407.     while (*cp && !strchr("._+-,@~=",*cp))
  3408.         *xp++ = *cp++;
  3409.  
  3410.     *xp = '\0';
  3411.  
  3412.     NameSegment[i] . Separator = *cp;
  3413.  
  3414.     if (*cp)
  3415.         cp++;
  3416.  
  3417.     if(NameSegment[i] . String[0] || NameSegment[i] . Separator)
  3418.         return(cp);
  3419.     else
  3420.         return(NULL);
  3421. }
  3422.  
  3423. STATIC VOID __regargs
  3424. CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,WORD Zap)
  3425. {
  3426.     UBYTE *cp = Destination,*xp;
  3427.  
  3428.     for(xp = NameSegment[0] . String ; *xp ; )
  3429.         *cp++ = *xp++;
  3430.  
  3431.     if(NameSegment[0] . Separator)
  3432.     {
  3433.         register WORD i;
  3434.  
  3435.         *cp++ = NameSegment[0] . Separator;
  3436.  
  3437.         for(i = Zap + 1 ; ; i++)
  3438.         {
  3439.             for(xp = NameSegment[i] . String ; *xp ; )
  3440.                 *cp++ = *xp++;
  3441.  
  3442.             if(NameSegment[i] . Separator)
  3443.                 *cp++ = NameSegment[i] . Separator;
  3444.             else
  3445.             {
  3446.                 if(!NameSegment[i] . String[0])
  3447.                     break;
  3448.             }
  3449.         }
  3450.     }
  3451.  
  3452.     *cp = 0;
  3453. }
  3454.  
  3455.     /* ShrinkName():
  3456.      *
  3457.      *    Shrink a file name down to a number of characters, if
  3458.      *    possible preserving the structure of the name. Algorithm
  3459.      *    courtesy of the "shrink" program by Simon Brown,
  3460.      *    Edinburgh University.
  3461.      */
  3462.  
  3463. UBYTE * __regargs
  3464. ShrinkName(const UBYTE *Source,UBYTE *Destination,WORD MaxLength,BOOLEAN FixSuffix)
  3465. {
  3466.     #define MAXSEGS 10
  3467.  
  3468.     struct NameSegment NameSegment[MAXSEGS];
  3469.  
  3470.     WORD i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
  3471.     UBYTE *OldPtr = (UBYTE *)Source;
  3472.  
  3473.     for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
  3474.  
  3475.     if(i < MAXSEGS)
  3476.     {
  3477.         NumSegments = i - 1;
  3478.  
  3479.         if((NumSegments * 2) < MaxLength)
  3480.         {
  3481.             SuffixLength = strlen(NameSegment[NumSegments] . String);
  3482.  
  3483.             if(SuffixLength > MaxLength - NumSegments - 1)
  3484.             {
  3485.                 SuffixLength = MaxLength - (2 * NumSegments) - 1;
  3486.  
  3487.                 NameSegment[NumSegments] . String[SuffixLength - 1] = 0;
  3488.             }
  3489.             else
  3490.             {
  3491.                 if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
  3492.                     Zap = NumSegments - (MaxLength-SuffixLength)/2;
  3493.             }
  3494.  
  3495.             if(NumSegments >= 1)
  3496.             {
  3497.                 for(i = Zap + 1 ; i <= NumSegments ; i++)
  3498.                 {
  3499.                     if(NameSegment[i] . Separator)
  3500.                         SuffixLength++;
  3501.                 }
  3502.  
  3503.                 if(NameSegment[0] . Separator)
  3504.                     SuffixLength++;
  3505.  
  3506.                 Remainder = MaxLength - SuffixLength;
  3507.  
  3508.                 Delete = Remainder / NumSegments;
  3509.  
  3510.                 Total = SuffixLength;
  3511.  
  3512.                 for(i = Zap + 1 ; i < NumSegments ; i++)
  3513.                 {
  3514.                     NameSegment[i] . String[Delete] = 0;
  3515.  
  3516.                     Total += Delete;
  3517.                 }
  3518.  
  3519.                 NameSegment[0] . String[MaxLength - Total] = 0;
  3520.             }
  3521.  
  3522.             CopyNameSegment(NameSegment,Destination,Zap);
  3523.         }
  3524.         else
  3525.             strcpy(Destination,Source);
  3526.     }
  3527.     else
  3528.         strcpy(Destination,Source);
  3529.  
  3530.     if(FixSuffix)
  3531.     {
  3532.         BOOLEAN    GotDot    = FALSE;
  3533.         LONG    Len    = strlen(Destination),Dots;
  3534.  
  3535.         for(i = Dots = 0 ; i < Len ; i++)
  3536.         {
  3537.             if(Destination[i] == '.')
  3538.                 Dots++;
  3539.         }
  3540.  
  3541.         if(!Dots)
  3542.         {
  3543.             if(Len < 4)
  3544.                 strcat(Destination,".___");
  3545.             else
  3546.                 Destination[Len - 4] = '.';
  3547.         }
  3548.  
  3549.         for(i = Len - 1 ; i >= 0 ; i--)
  3550.         {
  3551.             if(Destination[i] == '.')
  3552.             {
  3553.                 if(GotDot)
  3554.                     Destination[i] = '_';
  3555.                 else
  3556.                     GotDot = TRUE;
  3557.             }
  3558.  
  3559.             if(Destination[i] == '\\')
  3560.                 Destination[i] = '-';
  3561.         }
  3562.     }
  3563.  
  3564.     return(Destination);
  3565. }
  3566.  
  3567.     /* BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size):
  3568.      *
  3569.      *    Build a font name and size string from given
  3570.      *    information (raw name and size).
  3571.      */
  3572.  
  3573. VOID __regargs
  3574. BuildFontName(STRPTR Destination,const STRPTR Name,LONG Size)
  3575. {
  3576.     UBYTE    LocalBuffer[50];
  3577.     LONG    Len;
  3578.  
  3579.     strcpy(LocalBuffer,FilePart((STRPTR)Name));
  3580.  
  3581.     Len = strlen(LocalBuffer);
  3582.  
  3583.     if(Len > 5)
  3584.     {
  3585.         if(!Stricmp(&LocalBuffer[Len - 5],".font"))
  3586.             LocalBuffer[Len - 5] = 0;
  3587.     }
  3588.  
  3589.     SPrintf(Destination,"%s %ld",LocalBuffer,Size);
  3590. }
  3591.  
  3592.     /* CreateMenuGlyphs():
  3593.      *
  3594.      *    Create scaled glyphs for pull-down menus.
  3595.      */
  3596.  
  3597. BOOLEAN __regargs
  3598. CreateMenuGlyphs(struct Screen *Screen,struct DrawInfo *DrawInfo,struct Image **AmigaPtr,struct Image **CheckPtr)
  3599. {
  3600.     struct Image    *AmigaGlyph,
  3601.             *CheckGlyph;
  3602.     LONG         AspectX,AspectY,
  3603.              Size,FontHeight;
  3604.  
  3605.     FontHeight = DrawInfo -> dri_Font -> tf_Baseline + 2;
  3606.  
  3607.     if(Screen -> Flags & SCREENHIRES)
  3608.         Size = SYSISIZE_MEDRES;
  3609.     else
  3610.         Size = SYSISIZE_LOWRES;
  3611.  
  3612.     AspectX = DrawInfo -> dri_Resolution . X;
  3613.     AspectY = DrawInfo -> dri_Resolution . Y;
  3614.  
  3615.     if(AmigaGlyph = NewObject(NULL,SYSICLASS,
  3616.         SYSIA_DrawInfo,    DrawInfo,
  3617.         SYSIA_Size,    Size,
  3618.         SYSIA_Which,    AMIGAKEY,
  3619.         IA_Left,    0,
  3620.         LA_Top,        0,
  3621.         IA_Width,    (FontHeight * 3 * AspectY) / (2 * AspectX),
  3622.         IA_Height,    FontHeight,
  3623.     TAG_DONE))
  3624.     {
  3625.         if(!(CheckGlyph = NewObject(NULL,SYSICLASS,
  3626.             SYSIA_DrawInfo,    DrawInfo,
  3627.             SYSIA_Size,    Size,
  3628.             SYSIA_Which,    MENUCHECK,
  3629.             IA_Left,    0,
  3630.             LA_Top,        0,
  3631.             IA_Width,    (FontHeight * AspectY) / AspectX,
  3632.             IA_Height,    FontHeight,
  3633.         TAG_DONE)))
  3634.         {
  3635.             DisposeObject(AmigaGlyph);
  3636.  
  3637.             AmigaGlyph = NULL;
  3638.         }
  3639.     }
  3640.  
  3641.     if(AmigaGlyph && CheckGlyph)
  3642.     {
  3643.         *AmigaPtr = AmigaGlyph;
  3644.         *CheckPtr = CheckGlyph;
  3645.  
  3646.         return(TRUE);
  3647.     }
  3648.     else
  3649.         return(FALSE);
  3650. }
  3651.  
  3652.     /* FixName(STRPTR Name):
  3653.      *
  3654.      *    Build a correct AmigaDOS filename.
  3655.      */
  3656.  
  3657. VOID __regargs
  3658. FixName(STRPTR Name)
  3659. {
  3660.     WORD    NameLen    = strlen(Name),
  3661.         i;
  3662.  
  3663.         /* Replace special characters. */
  3664.  
  3665.     for(i = 0 ; i < NameLen ; i++)
  3666.     {
  3667.         switch(Name[i])
  3668.         {
  3669.             case ' ':
  3670.  
  3671.                 Name[i] = '_';
  3672.                 break;
  3673.  
  3674.             case ':':
  3675.  
  3676.                 Name[i] = '.';
  3677.                 break;
  3678.  
  3679.             case '/':
  3680.  
  3681.                 Name[i] = '\\';
  3682.                 break;
  3683.  
  3684.             case '\"':
  3685.  
  3686.                 Name[i] = '\'';
  3687.                 break;
  3688.         }
  3689.     }
  3690.  
  3691.         /* Truncate the name. */
  3692.  
  3693.     if(NameLen > 31)
  3694.         Name[31] = 0;
  3695. }
  3696.  
  3697.     /* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
  3698.      *
  3699.      *    Display an error message, in human readable form if possible.
  3700.      */
  3701.  
  3702. VOID __regargs
  3703. ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
  3704. {
  3705.     STATIC LONG LocalErrors[][2] =
  3706.     {
  3707.         ERR_SAVE_ERROR,            MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
  3708.         ERR_LOAD_ERROR,            MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
  3709.         ERR_NO_MEM,            MSG_ERR_NO_MEM_TXT,
  3710.         ERR_OUTDATED,            MSG_ERR_OUTDATED_TXT,
  3711.  
  3712.         IFFERR_NOMEM,            MSG_IFFERR_NOMEM_TXT,
  3713.         IFFERR_READ,            MSG_IFFERR_READ_TXT,
  3714.         IFFERR_WRITE,            MSG_IFFERR_WRITE_TXT,
  3715.         IFFERR_SEEK,            MSG_IFFERR_SEEK_TXT,
  3716.         IFFERR_MANGLED,            MSG_IFFERR_MANGLED_TXT,
  3717.         IFFERR_NOTIFF,            MSG_IFFERR_NOTIFF_TXT,
  3718.  
  3719.         0,                0
  3720.     };
  3721.  
  3722.     STRPTR    PrimaryError    = NULL,
  3723.         SecondaryError    = NULL;
  3724.  
  3725.     if(Primary)
  3726.     {
  3727.         LONG i;
  3728.  
  3729.         for(i = 0 ; LocalErrors[i][0] ; i++)
  3730.         {
  3731.             if(LocalErrors[i][0] == Primary)
  3732.             {
  3733.                 PrimaryError = LocaleString(LocalErrors[i][1]);
  3734.  
  3735.                 break;
  3736.             }
  3737.         }
  3738.  
  3739.         if(!PrimaryError)
  3740.         {
  3741.             STATIC UBYTE __far Buffer[256];
  3742.  
  3743.             Fault(Primary,"",Buffer,256);
  3744.  
  3745.             PrimaryError = Buffer + 2;
  3746.         }
  3747.     }
  3748.  
  3749.     if(Secondary)
  3750.     {
  3751.         LONG i;
  3752.  
  3753.         for(i = 0 ; LocalErrors[i][0] ; i++)
  3754.         {
  3755.             if(LocalErrors[i][0] == Secondary)
  3756.             {
  3757.                 SecondaryError = LocaleString(LocalErrors[i][1]);
  3758.  
  3759.                 break;
  3760.             }
  3761.         }
  3762.  
  3763.         if(!SecondaryError)
  3764.         {
  3765.             STATIC UBYTE __far Buffer[256];
  3766.  
  3767.             Fault(Secondary,"",Buffer,256);
  3768.  
  3769.             SecondaryError = Buffer + 2;
  3770.         }
  3771.     }
  3772.  
  3773.     if(PrimaryError)
  3774.     {
  3775.         if(String)
  3776.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
  3777.         else
  3778.             MyEasyRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
  3779.     }
  3780. }
  3781.  
  3782. struct RendezvousData * __saveds __asm
  3783. RendezvousLogin(register __a0 struct MsgPort *ReadPort,register __a1 struct MsgPort *WritePort,register __a2 struct TagItem *TagList)
  3784. {
  3785.     struct RendezvousData *Data;
  3786.  
  3787.     if(Data = (struct RendezvousData *)AllocVecPooled(sizeof(struct RendezvousData),MEMF_ANY | MEMF_CLEAR))
  3788.     {
  3789.         struct DataMsg Msg;
  3790.  
  3791.         InitMsgItem(&Msg,TaskDestructor);
  3792.  
  3793.         Msg . Type = DATAMSGTYPE_RENDEZVOUS;
  3794.         Msg . Data = (UBYTE *)SysBase -> ThisTask;
  3795.  
  3796.         ClrSignal(SIG_HANDSHAKE);
  3797.  
  3798.         PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  3799.  
  3800.         Wait(SIG_HANDSHAKE);
  3801.  
  3802.         if(ReadRequest && WriteRequest)
  3803.         {
  3804.             struct List *UploadList;
  3805.  
  3806.             CopyMem(ReadRequest,&Data -> rd_ReadRequest,sizeof(struct IOExtSer));
  3807.  
  3808.             Data -> rd_ReadRequest . IOSer . io_Message . mn_ReplyPort = ReadPort;
  3809.  
  3810.             CopyMem(WriteRequest,&Data -> rd_WriteRequest,sizeof(struct IOExtSer));
  3811.  
  3812.             Data -> rd_WriteRequest . IOSer . io_Message . mn_ReplyPort = WritePort;
  3813.  
  3814.             if(Window)
  3815.                 Data -> rd_Screen = Window -> WScreen;
  3816.  
  3817.             NewList(&Data -> rd_UploadList);
  3818.             NewList(&Data -> rd_DownloadList);
  3819.             NewList(&Data -> rd_SentList);
  3820.             NewList(&Data -> rd_ReceivedList);
  3821.  
  3822.             if(UploadList = GetUploadList())
  3823.             {
  3824.                 struct Node *Node,*Next;
  3825.  
  3826.                 for(Node = UploadList -> lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3827.                     AddTail(&Data -> rd_UploadList,Node);
  3828.  
  3829.                 FreeVecPooled(UploadList);
  3830.             }
  3831.  
  3832.             Data -> rd_SendPath    = Config -> PathConfig -> BinaryUploadPath;
  3833.             Data -> rd_ReceivePath    = Config -> PathConfig -> BinaryDownloadPath;
  3834.             Data -> rd_Options    = "";
  3835.         }
  3836.         else
  3837.         {
  3838.             FreeVecPooled(Data);
  3839.  
  3840.             Data = NULL;
  3841.         }
  3842.     }
  3843.  
  3844.     return(Data);
  3845. }
  3846.  
  3847. VOID __saveds __asm
  3848. RendezvousLogoff(register __a0 struct RendezvousData *Data)
  3849. {
  3850.     if(Data)
  3851.     {
  3852.         struct Node *Node,*Next;
  3853.  
  3854.         for(Node = Data -> rd_UploadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3855.             FreeVecPooled(Node);
  3856.  
  3857.         for(Node = Data -> rd_DownloadList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3858.             FreeVecPooled(Node);
  3859.  
  3860.         for(Node = Data -> rd_SentList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3861.             FreeVecPooled(Node);
  3862.  
  3863.         for(Node = Data -> rd_ReceivedList . lh_Head ; Next = Node -> ln_Succ ; Node = Next)
  3864.             FreeVecPooled(Node);
  3865.  
  3866.         FreeVecPooled(Data);
  3867.  
  3868.         Signal(ThisProcess,SIG_HANDSHAKE);
  3869.     }
  3870. }
  3871.  
  3872. struct Node * __saveds __asm
  3873. RendezvousNewNode(register __a0 STRPTR Name)
  3874. {
  3875.     if(Name)
  3876.     {
  3877.         LONG Len;
  3878.  
  3879.         if(Len = strlen(Name))
  3880.         {
  3881.             struct Node *Node;
  3882.  
  3883.             if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + Len + 1,MEMF_ANY))
  3884.             {
  3885.                 memset(Node,0,sizeof(struct Node));
  3886.  
  3887.                 strcpy(Node -> ln_Name = (STRPTR)(Node + 1),Name);
  3888.  
  3889.                 return(Node);
  3890.             }
  3891.         }
  3892.     }
  3893.  
  3894.     return(NULL);
  3895. }
  3896.